D.gnu - [Bug 101] New: DLL sample for GDC
- gdc-bugzilla gdcproject.org (240/240) Feb 01 2014 http://bugzilla.gdcproject.org/show_bug.cgi?id=101
http://bugzilla.gdcproject.org/show_bug.cgi?id=101 Summary: DLL sample for GDC Classification: Unclassified Product: GDC Version: development Platform: x86 OS/Version: Other Status: NEW Severity: major Priority: Normal Component: gdc AssignedTo: ibuclaw gdcproject.org ReportedBy: slavo5150 yahoo.com This was migrated from https://bitbucket.org/goshawk/gdc/issue/288/dll-sample-for-gdc Andrej08 created an issue 2011-12-16 **************************************** Since this will probably be an often-asked question, I think it would be nice to package a DLL sample in some "Samples" directory or maybe on the wiki page. Here's a preliminary sample that works: mydll.d: module mydll; import std.c.windows.windows; version (Windows) { extern (C) bool rt_init( void delegate( Exception ) dg = null ); extern (C) bool rt_term( void delegate( Exception ) dg = null ); // Globals static HINSTANCE g_hInst; extern (Windows) BOOL DllMain(HINSTANCE hInstance, ULONG ulReason, LPVOID pvReserved) { int argc; char** argv; switch (ulReason) { case DLL_PROCESS_ATTACH: rt_init(); break; case DLL_PROCESS_DETACH: rt_term(); break; case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: return false; default: break; } g_hInst = hInstance; return true; } } export extern(D) int sum(int x, int y) { return x + y; } main.d: module main; import mydll; import std.stdio; void main() { int x = 1; int y = 2; writefln("The sum of %s and %s is %s.", x, y, sum(x, y)); } build.bat: echo off gdc -fintfc -v2 -fsyntax-only -H mydll.d gdc -v2 -shared -o mydll.dll mydll.d -Wl,--out-implib,implibmydll.a gdc -v2 -o main.exe main.d implibmydll.a Unfortunately this isn't reliable since I'm not doing extra work when threads get involved. I had to prototype rt_init and rt_term because I can't import import core.sys.windows.dll and use dll_process_attach and dll_process_detach due to linking errors. Example: module mydll; import std.c.windows.windows; import core.sys.windows.dll; __gshared HINSTANCE g_hInst; version (Windows) { extern (Windows) BOOL DllMain(HINSTANCE hInstance, ULONG ulReason, LPVOID pvReserved) { switch (ulReason) { case DLL_PROCESS_ATTACH: dll_process_attach( hInstance, true ); break; case DLL_PROCESS_DETACH: dll_process_detach( hInstance, true ); break; case DLL_THREAD_ATTACH: dll_thread_attach( true, true ); break; case DLL_THREAD_DETACH: dll_thread_detach( true, true ); return false; default: break; } g_hInst = hInstance; return true; } } export extern(D) int sum(int x, int y) { return x + y; } gdc -v2 -shared -o mydll.dll mydll.d -Wl,--out-implib,implibmydll.a Creating library file: implibmydll.a d:/mingw32/bin/../lib/gcc/i686-pc-mingw32/4.6.1/../../../libgphobos2.a(dll.o): In function `D4core3sys7windows3dll18dll_process_attachFPvbZb': C:\crossdev\gdc\v2\build\i686-pc-mingw32\libphobos/../../../gcc-4.6.1/libphobos/core/sys/windows/dll.d:386: undefined reference to `_tls_callbacks_a' collect2: ld returned 1 exit status There is a workaround, I can define a dummy symbol called _tls_callbacks_a: module mydll; import std.c.windows.windows; import core.sys.windows.dll; __gshared HINSTANCE g_hInst; extern(C) int _tls_callbacks_a; version (Windows) { extern (Windows) BOOL DllMain(HINSTANCE hInstance, ULONG ulReason, LPVOID pvReserved) { switch (ulReason) { case DLL_PROCESS_ATTACH: dll_process_attach( hInstance, true ); break; case DLL_PROCESS_DETACH: dll_process_detach( hInstance, true ); break; case DLL_THREAD_ATTACH: dll_thread_attach( true, true ); break; case DLL_THREAD_DETACH: dll_thread_detach( true, true ); return false; default: break; } g_hInst = hInstance; return true; } } export extern(D) int sum(int x, int y) { return x + y; } This will successfully compile the DLL. The other problem is an issue with DMD's front-end (I think so anyway, and GDC is based on that front-end AFAIK), where using a .di file will create a dependency on a symbol "ModuleInfoZ". I've discussed this in Issue 6019 (http://d.puremagic.com/issues/show_bug.cgi?id=6019), essentially the linker error after the last call here: gdc -v2 -shared -o mydll.dll mydll.d -Wl,--out-implib,implibmydll.a gdc -fintfc -v2 -fsyntax-only -H mydll.d gdc -v2 -o main.exe main.d implibmydll.a is: C:\DOCUME~1\Andrej\LOCALS~1\Temp\ccMiZJOR.o:main.d:(.data+0xc): undefined reference to `_D5mydll12__ModuleInfoZ' To work around that, another dummy symbol must be added to main.d: module main; import mydll; import std.stdio; extern(C) int _D5mydll12__ModuleInfoZ; void main() { int x = 1; int y = 2; writefln("The sum of %s and %s is %s.", x, y, sum(x, y)); } Anyway I just thought this info would be useful here. Andrej08 - 2011-12-16 ************************************** Actually there is one more workaround to the ModuleInfoZ problem, it's to use function-local import to core.sys.windows.dll, e.g.: module mydll; import std.c.windows.windows; __gshared HINSTANCE g_hInst; extern(C) int _tls_callbacks_a; version (Windows) { extern (Windows) BOOL DllMain(HINSTANCE hInstance, ULONG ulReason, LPVOID pvReserved) { import core.sys.windows.dll; switch (ulReason) { case DLL_PROCESS_ATTACH: dll_process_attach( hInstance, true ); break; case DLL_PROCESS_DETACH: dll_process_detach( hInstance, true ); break; case DLL_THREAD_ATTACH: dll_thread_attach( true, true ); break; case DLL_THREAD_DETACH: dll_thread_detach( true, true ); return false; default: break; } g_hInst = hInstance; return true; } } export extern(D) int sum(int x, int y) { return x + y; } Daniel Green - 2012-01-26 **************************************************** * assigned issue to Daniel Green _tls_callbacks_a is a Digital Mars thing. I believe Visual Studio and MinGW use xl_a. It's a pointer to the start of the TLS callbacks. I'll look into this. It may only require alias __xl_a _tls_callbacks and the approriate extern definition for xl_a. Daniel Green - 2012-01-28 ***************************************** Another workaround for 'ModuleInfoZ' is to use -Wl,--export-all-symbols. It is defined, but it's not exported from the Dll. The only issue here, is you can't generate the library file and must link with the Dll. gdc -v2 -shared -o mydll.dll mydll.d -Wl,--export-all-symbols gdc -v2 -fintfc -fsyntax-only -H mydll.d gdc -v2 -o main.exe main.d mydll.dll Do you think it would be safe to apply the export attribute to generated 'ModuleInfoZ' symbol? Edit: It also seems DMD wishes to have all ModuleInfoZ symbols declared weak. So that the inability to import one will not prevent linking. -- Configure bugmail: http://bugzilla.gdcproject.org/userprefs.cgi?tab=email ------- You are receiving this mail because: ------- You are watching all bug changes.
Feb 01 2014