[Bug 101] New: DLL sample for GDC
gdc-bugzilla at gdcproject.org
gdc-bugzilla at gdcproject.org
Sat Feb 1 03:19:56 PST 2014
http://bugzilla.gdcproject.org/show_bug.cgi?id=101
Bug #: 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 at gdcproject.org
ReportedBy: slavo5150 at 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.
More information about the D.gnu
mailing list