digitalmars.D - instance of sub class created in a dll has wired behaviour when cast
- liyu (94/94) Mar 22 2009 I am not sure it's a bug of tango or dmd, so i post it here. The example...
- Jarrett Billingsley (10/21) Mar 22 2009 This is, unfortunately, a limitation imposed by Windows DLLs. DLLs
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.AssertException 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.
Mar 22 2009
2009/3/22 liyu <yunwind msn.com>:I am not sure it's a bug of tango or dmd, so i post it here. The example code as below ... The result is: Library successfully loaded Symbol dllprint found. Address = 0x1000308c mydll.DummyC mydll.DummyC tango.core.Exception.AssertException 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.This is, unfortunately, a limitation imposed by Windows DLLs. DLLs cannot, by their nature, load symbols out of the host application that loads them. As a result, the typeinfo of classes is duplicated, one copy in the host and one in each DLL. Thus you end up with classes which _look_ the same, but casting them will inevitably fail. There is no real robust solution while still using DLLs, and the problem only exists on Windows. DDL attempts (and succeeds, quite nicely) in performing manual dynamic linking. http://www.dsource.org/projects/ddl
Mar 22 2009
"Jarrett Billingsley" <jarrett.billingsley gmail.com> wrote in message news:mailman.986.1237779483.22690.digitalmars-d puremagic.com...2009/3/22 liyu <yunwind msn.com>:wow, I never known that before, thanks!I am not sure it's a bug of tango or dmd, so i post it here. The example code as below ... The result is: Library successfully loaded Symbol dllprint found. Address = 0x1000308c mydll.DummyC mydll.DummyC tango.core.Exception.AssertException 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.This is, unfortunately, a limitation imposed by Windows DLLs. DLLs cannot, by their nature, load symbols out of the host application that loads them. As a result, the typeinfo of classes is duplicated, one copy in the host and one in each DLL. Thus you end up with classes which _look_ the same, but casting them will inevitably fail. There is no real robust solution while still using DLLs, and the problem only exists on Windows. DDL attempts (and succeeds, quite nicely) in performing manual dynamic linking. http://www.dsource.org/projects/ddl
Mar 22 2009
在 Mon, 23 Mar 2009 11:37:56 +0800,Jarrett Billingsley <jarrett.billingsley gmail.com> 写道:2009/3/22 liyu <yunwind msn.com>:I think if the runtime typeinfo is modularized to a seperated dll, the problem should go away. Just on one think that's a must at the moment.I am not sure it's a bug of tango or dmd, so i post it here. The example code as below ... The result is: Library successfully loaded Symbol dllprint found. Address = 0x1000308c mydll.DummyC mydll.DummyC tango.core.Exception.AssertException 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.This is, unfortunately, a limitation imposed by Windows DLLs. DLLs cannot, by their nature, load symbols out of the host application that loads them. As a result, the typeinfo of classes is duplicated, one copy in the host and one in each DLL. Thus you end up with classes which _look_ the same, but casting them will inevitably fail. There is no real robust solution while still using DLLs, and the problem only exists on Windows. DDL attempts (and succeeds, quite nicely) in performing manual dynamic linking. http://www.dsource.org/projects/ddl
Mar 22 2009