| Thread overview | ||||||
|---|---|---|---|---|---|---|
|
March 23, 2009 instance of sub class created in a dll has wired behaviour when cast | ||||
|---|---|---|---|---|
| ||||
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.
| ||||
March 23, 2009 Re: instance of sub class created in a dll has wired behaviour when cast | ||||
|---|---|---|---|---|
| ||||
Posted in reply to liyu | 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 | |||
March 23, 2009 Re: instance of sub class created in a dll has wired behaviour when cast | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Jarrett Billingsley | "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>: >> 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 wow, I never known that before, thanks! | |||
March 23, 2009 Re: instance of sub class created in a dll has wired behaviour when cast | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Jarrett Billingsley | 在 Mon, 23 Mar 2009 11:37:56 +0800,Jarrett Billingsley <jarrett.billingsley@gmail.com> 写道: > 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 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. | |||
Copyright © 1999-2021 by the D Language Foundation
Permalink
Reply