I am not sure it's a bug of tango or dmd, so i post it here. The example code as below

//file common
module common;

abstract class DummyA {

}

abstract class DummyB : DummyA {

}

abstract class Factory {
        DummyB createDummy();
}

//file dll
module mydll;

import common;

import tango.sys.win32.Types;

import tango.io.Stdout;
import tango.stdc.stdio;

// The core DLL init code.
extern (C) bool  rt_init( void delegate( Exception ) dg = null );
extern (C) bool  rt_term( void delegate( Exception ) dg = null );

HINSTANCE g_hInst;

extern (Windows)
BOOL DllMain(HINSTANCE hInstance, ULONG ulReason, LPVOID pvReserved)
{
   switch (ulReason)
   {
        case DLL_PROCESS_ATTACH:
                rt_init();
            break;

        case DLL_PROCESS_DETACH:
                tango.stdc.stdio._fcloseallp = null;
                rt_term();
            break;

        case DLL_THREAD_ATTACH:
        case DLL_THREAD_DETACH:
            // Multiple threads not supported yet
            return false;
   }
   g_hInst=hInstance;
   return true;
}

class DummyC : DummyB {

}

class DllFactory : Factory {
        override DummyC createDummy() {
return new DummyC; }
}

export extern(C) DllFactory create() {
        return new DllFactory;}

//file test
module test;

import common;

import tango.sys.SharedLib;
import tango.util.log.Trace;

// declaring our function pointer
typedef extern (C) Factory function() createFunc;
createFunc dllcreate;

void main() {
   if (auto lib = SharedLib.load(`mydll.dll`)) {
       Trace.formatln("Library successfully loaded");

       void* ptr = lib.getSymbol("create");
       if (ptr) {
           Trace.formatln("Symbol dllprint found. Address = 0x{:x}", ptr);

           // binding function address from DLL to our function pointer
           void **point = cast(void **)&dllcreate;
           *point = ptr;

           // using our function
           auto factory = dllcreate();
           auto dummy = factory.createDummy();

           Trace.formatln(dummy.classinfo.name);
           auto d2 = cast(DummyB)dummy;
           assert(d2 !is null); //ok

           DummyA a = dummy;
           Trace.formatln(a.classinfo.name);
           auto d3 = cast(DummyB)a;
           assert(d3 !is null);    //Assertion failure

       } else {
           Trace.formatln("Symbol dllprint not found");
       }

       lib.unload();
   } else {
       Trace.formatln("Could not load the library");
   }

   assert (0 == SharedLib.numLoadedLibs);
}

The result is:
Library successfully loaded
Symbol dllprint found. Address = 0x1000308c
mydll.DummyC
mydll.DummyC
tango.core.exception.assertexcept...@test(35): Assertion failure

As you see, var a is a instance of DummyC which is a subclass of DummyB, but the cast is failure.


Reply via email to