digitalmars.D.learn - DLLs and headaches
- Unknown W. Brackets (153/153) May 04 2009 This is kinda complicated, hopefully someone will still read it and try ...
- Don (6/21) May 04 2009 Is this D1 or D2?
- Unknown W. Brackets (8/32) May 04 2009 D2; but actually, it kinda works. It crashes on freeing the library,
- Richard Webb (8/12) Sep 17 2009 Hi,
- Don (4/21) Sep 25 2009 Indeed it does. Thanks for the link, that's tremendously helpful.
This is kinda complicated, hopefully someone will still read it and try it. DLLs typically don't have access to the host process. Sometimes, when creating plugins, such access may be desirable. The typical solution is to have the host and plugins both load a secondary DLL. I've tried to replicate this with D. I have a stub program, a "primary" dll, and a "plugin" dll. Although the solution in itself does work, I'm having a lot of problems and they seem related to D. But, maybe I'm just doing it all wrong? If I import std.stdio in a DLL, it won't compile. Period. Otherwise, the primary DLL never finishes - it just dies when it frees the plugin library. There are a bunch of files, unfortunately. Listing below: --- test.d --- import std.c.stdio; import primary; extern (C) void* gc_getProxy(); // Just a stub to load the primary code. int main() { printf("Entering main().\n"); primary_init(gc_getProxy()); int ret = primary_main(); primary_terminate(); printf("Exiting main().\n"); return ret; } --------- --- plugin.d --- import core.runtime; import std.c.stdio; import std.c.windows.windows; import primary; extern (Windows) BOOL DllMain(HINSTANCE hInstance, ULONG ulReason, LPVOID pvReserved) { switch (ulReason) { case DLL_PROCESS_ATTACH: printf("DLL_PROCESS_ATTACH -> plugin\n"); Runtime.initialize(); break; case DLL_PROCESS_DETACH: printf("DLL_PROCESS_DETACH -> plugin\n"); Runtime.terminate(); break; case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: return false; } return true; } // This is just here to load a plugin and export anything. export void dummy() { } --------- --- plugin.def --- LIBRARY plugin DESCRIPTION 'Plugin Example' EXETYPE NT CODE PRELOAD DISCARDABLE DATA PRELOAD SINGLE --------- --- primary.d --- import std.c.windows.windows; import core.runtime; import std.c.stdio; // SKIP_RUNTIME uses Windows instead of Runtime.*, makes no difference. // FAIL2 shows that it won't even compile with std.stdio. version (FAIL2) import std.stdio; extern (Windows) BOOL DllMain(HINSTANCE hInstance, ULONG ulReason, LPVOID pvReserved) { switch (ulReason) { case DLL_PROCESS_ATTACH: printf("DLL_PROCESS_ATTACH -> primary\n"); Runtime.initialize(); break; case DLL_PROCESS_DETACH: printf("DLL_PROCESS_DETACH -> primary\n"); Runtime.terminate(); break; case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: return false; } return true; } extern (C) { void gc_setProxy(void* p); void gc_clrProxy(); } export void primary_init(void* gc) { printf("primary_init()\n"); gc_setProxy(gc); } export void primary_terminate() { printf("primary_terminate()\n"); gc_clrProxy(); } export int primary_main() { HMODULE h; FARPROC fp; bool unloaded; printf("Start Dynamic Link...\n"); version (SKIP_RUNTIME) h = LoadLibraryA("plugin.dll"); else h = cast(HMODULE) Runtime.loadLibrary("plugin.dll"); if (h is null) { printf("error loading plugin.dll\n"); return 1; } version (FAIL2) writefln("hi"); version (SKIP_RUNTIME) unloaded = FreeLibrary(h) != 0; else unloaded = Runtime.unloadLibrary(h); if (!unloaded) { printf("error freeing plugin.dll\n"); return 1; } printf("End...\n"); return 0; } --------- --- primary.def --- LIBRARY primary DESCRIPTION 'Primary Program' EXETYPE NT CODE PRELOAD DISCARDABLE DATA PRELOAD SINGLE --------- --- compilation --- echo === Compile the primary DLL. dmd primary.d primary.def -g -L/map implib /noi /system primary.lib primary.dll echo === Compile the example plugin. dmd plugin.d plugin.def primary.lib -g -L/map echo === Compile the stub. dmd test.d primary.lib -g --------- Anyone know anything? -[Unknown]
May 04 2009
Unknown W. Brackets wrote:This is kinda complicated, hopefully someone will still read it and try it. DLLs typically don't have access to the host process. Sometimes, when creating plugins, such access may be desirable. The typical solution is to have the host and plugins both load a secondary DLL. I've tried to replicate this with D. I have a stub program, a "primary" dll, and a "plugin" dll. Although the solution in itself does work, I'm having a lot of problems and they seem related to D. But, maybe I'm just doing it all wrong? If I import std.stdio in a DLL, it won't compile. Period. Otherwise, the primary DLL never finishes - it just dies when it frees the plugin library.Is this D1 or D2? If D2 -- I haven't been able to get D2 DLLs to work at all. They just crash during the initialization (something to do with initialising the thread-locals, I think, but I haven't been able to track it down completely).
May 04 2009
D2; but actually, it kinda works. It crashes on freeing the library, but it loads fine. If I use std.stdio, link says that primary.__ModuleInfo is missing, but that just means it crashes during compile/link. That said, I'm very dissapointed that Runtime doesn't support Posix yet. Means I'll have to roll it myself anyway. -[Unknown] Don wrote:Unknown W. Brackets wrote:This is kinda complicated, hopefully someone will still read it and try it. DLLs typically don't have access to the host process. Sometimes, when creating plugins, such access may be desirable. The typical solution is to have the host and plugins both load a secondary DLL. I've tried to replicate this with D. I have a stub program, a "primary" dll, and a "plugin" dll. Although the solution in itself does work, I'm having a lot of problems and they seem related to D. But, maybe I'm just doing it all wrong? If I import std.stdio in a DLL, it won't compile. Period. Otherwise, the primary DLL never finishes - it just dies when it frees the plugin library.Is this D1 or D2? If D2 -- I haven't been able to get D2 DLLs to work at all. They just crash during the initialization (something to do with initialising the thread-locals, I think, but I haven't been able to track it down completely).
May 04 2009
Don Wrote:If D2 -- I haven't been able to get D2 DLLs to work at all. They just crash during the initialization (something to do with initialising the thread-locals, I think, but I haven't been able to track it down completely).Hi, I've recently been having a go at writing a COM object in D, and have run into this when trying it in D2. Debugging through it, i get a crash on the void* pstart = cast(void*) &_tlsstart; on line 1192 of thread.d, due to a null pointer access. This sounds like the issue described at http://www.nynaeve.net/?p=187 ? Is this a known problem with D2 ?
Sep 17 2009
Richard Webb wrote:Don Wrote:Yes, that's the exact same place where it crashed for me.If D2 -- I haven't been able to get D2 DLLs to work at all. They just crash during the initialization (something to do with initialising the thread-locals, I think, but I haven't been able to track it down completely).Hi, I've recently been having a go at writing a COM object in D, and have run into this when trying it in D2. Debugging through it, i get a crash on the void* pstart = cast(void*) &_tlsstart; on line 1192 of thread.d, due to a null pointer access.This sounds like the issue described at http://www.nynaeve.net/?p=187 ?Indeed it does. Thanks for the link, that's tremendously helpful.Is this a known problem with D2 ?It wasn't, but it is now. Walter has created bugzilla 3342.
Sep 25 2009