digitalmars.D.learn - Shared libraries/DLLs
- Unknown W. Brackets (49/49) Jan 31 2008 This might be a silly or simple question. I haven't really used shared
- Jarrett Billingsley (3/14) Jan 31 2008 So, uh, what _exactly_ is the problem? I don't think you ever said..
- Unknown W. Brackets (9/29) Jan 31 2008 Sorry, I want to be able to compile and run that. It refuses to do so.
- Neal Alexander (11/45) Jan 31 2008 If the settings used in your .def file aren't particular the DLL doesnt
- Unknown W. Brackets (8/20) Jan 31 2008 Thanks. Actually, I have no trouble whatsoever making dlls. I have a
- Jarrett Billingsley (6/9) Feb 01 2008 You shouldn't need a .def file at all for this program. In fact, you sh...
- Unknown W. Brackets (4/18) Feb 01 2008 Well, the def being for the library, not for the program loading the
- Jarrett Billingsley (5/7) Feb 01 2008 In that case, I'd be more interested to see how you're compiling all thi...
- Unknown W. Brackets (97/107) Feb 01 2008 Okay.
- Jarrett Billingsley (7/17) Feb 02 2008 Ohhh, _there_ it is; I think this bit got cut out of the original post :...
- Jarrett Billingsley (8/14) Feb 02 2008 However there's hope: DDL. http://www.dsource.org/projects/ddl
- Unknown W. Brackets (5/25) Feb 02 2008 Yes, I looked at that and tried it, but I'm afraid I may not have the
- Jarrett Billingsley (4/6) Feb 02 2008 It already uses Tango, and doesn't depend on Mango anymore, AFAIK. I wa...
- Unknown W. Brackets (5/14) Feb 02 2008 Ah, that's good news. I just did the download, and didn't think to
- Unknown W. Brackets (8/17) Feb 04 2008 Hello again,
- Jarrett Billingsley (3/8) Feb 05 2008 I have 286.
- Unknown W. Brackets (5/17) Feb 07 2008 Okay, no love there. What version of Tango are you using with it?
- Jarrett Billingsley (4/6) Feb 08 2008 The last time I tried it out I think I was using 0.99.3; I'll admit I
- bearophile (16/17) Feb 04 2008 It looks really nice.
- Neal Alexander (6/32) Feb 03 2008 Ive never had problems resolving an .exe's exported symbols at runtime.
- Unknown W. Brackets (14/48) Feb 03 2008 I'm not wanting to have to do that from the DLL.
- Bjoern (29/29) Feb 01 2008 Hm,
- Tomasz Polachowski (4/37) Feb 03 2008 (...)
- Unknown W. Brackets (9/49) Feb 03 2008 This is useless for plugins because I have no idea what the module name
This might be a silly or simple question. I haven't really used shared libraries very much, but have need to now. On Linux with gdc, everything (seems to be) fine. I can make everything work there fine. My problem is with Windows and dmd. Consider the following simple "library": --- module library; import loader; // (the DllMain stuff from D's doc pages.) extern (C) export int foo() { return 42 * loader.bar(); } --- And also consider this "application": --- module loader; import std.c.windows.windows; import std.string, std.stdio; extern (C) alias int function() example_f; void main() { HMODULE m = cast(HMODULE) LoadLibraryA(toStringz("library.dll")); example_f f = cast(example_f) GetProcAddress(m, toStringz("foo")); if (f) writefln("%d", f()); FreeLibrary(m); } extern (C) export int bar() { return 2; } --- This appears to work on Linux. I expected it might work (or there might be some way to coax it to work) on Windows. It seems logical, even not having used the LoadLibrary/etc. stuff before. The library needs to access the caller's functions. It does appear I can make it at least *compile* (but not run) by adding an IMPORTS directive to the .def file of the library, but this clearly is intended for static linking. I'm wanting to load the DLL as a plugin, dynamically. Its name and location might change. Am I making some hopefully obvious and stupid mistake? Please tell me I don't actually have to send pointers to all the api functions to the DLL when calling it. Thanks, -[Unknown]
Jan 31 2008
"Unknown W. Brackets" <unknown simplemachines.org> wrote in message news:fnu7l0$2p5l$1 digitalmars.com...This appears to work on Linux. I expected it might work (or there might be some way to coax it to work) on Windows. It seems logical, even not having used the LoadLibrary/etc. stuff before. The library needs to access the caller's functions. It does appear I can make it at least *compile* (but not run) by adding an IMPORTS directive to the .def file of the library, but this clearly is intended for static linking. I'm wanting to load the DLL as a plugin, dynamically. Its name and location might change. Am I making some hopefully obvious and stupid mistake? Please tell me I don't actually have to send pointers to all the api functions to the DLL when calling it.So, uh, what _exactly_ is the problem? I don't think you ever said..
Jan 31 2008
Sorry, I want to be able to compile and run that. It refuses to do so. It wants to link against loader.obj, except that defeats the purpose of it being dynamic. I can add IMPORTS to the def, but then it has to be static. I want to dynamically link, and also call functions from the code that is dynamically linking. Sorry I was unclear. -[Unknown] Jarrett Billingsley wrote:"Unknown W. Brackets" <unknown simplemachines.org> wrote in message news:fnu7l0$2p5l$1 digitalmars.com...This appears to work on Linux. I expected it might work (or there might be some way to coax it to work) on Windows. It seems logical, even not having used the LoadLibrary/etc. stuff before. The library needs to access the caller's functions. It does appear I can make it at least *compile* (but not run) by adding an IMPORTS directive to the .def file of the library, but this clearly is intended for static linking. I'm wanting to load the DLL as a plugin, dynamically. Its name and location might change. Am I making some hopefully obvious and stupid mistake? Please tell me I don't actually have to send pointers to all the api functions to the DLL when calling it.So, uh, what _exactly_ is the problem? I don't think you ever said..
Jan 31 2008
Unknown W. Brackets wrote:Sorry, I want to be able to compile and run that. It refuses to do so. It wants to link against loader.obj, except that defeats the purpose of it being dynamic. I can add IMPORTS to the def, but then it has to be static. I want to dynamically link, and also call functions from the code that is dynamically linking. Sorry I was unclear. -[Unknown] Jarrett Billingsley wrote:If the settings used in your .def file aren't particular the DLL doesnt work as expected. IIRC the def files in the digital mars DLL tutorial diddnt work for me when i first looked at it. maybe try this instead: ----------------------------------- LIBRARY "x.dll" DESCRIPTION 'x.dll' EXETYPE NT CODE PRELOAD DATA PRELOAD"Unknown W. Brackets" <unknown simplemachines.org> wrote in message news:fnu7l0$2p5l$1 digitalmars.com...This appears to work on Linux. I expected it might work (or there might be some way to coax it to work) on Windows. It seems logical, even not having used the LoadLibrary/etc. stuff before. The library needs to access the caller's functions. It does appear I can make it at least *compile* (but not run) by adding an IMPORTS directive to the .def file of the library, but this clearly is intended for static linking. I'm wanting to load the DLL as a plugin, dynamically. Its name and location might change. Am I making some hopefully obvious and stupid mistake? Please tell me I don't actually have to send pointers to all the api functions to the DLL when calling it.So, uh, what _exactly_ is the problem? I don't think you ever said..
Jan 31 2008
Thanks. Actually, I have no trouble whatsoever making dlls. I have a problem referencing functions in the program that loaded the DLL. It turns out (from something I'm read) what I want is simply not possibly with DLLs. I will have to send a pointer table/struct over on to the plugin for this to work the way I want. Ain't Linux better? Oi. -[Unknown] Neal Alexander wrote:If the settings used in your .def file aren't particular the DLL doesnt work as expected. IIRC the def files in the digital mars DLL tutorial diddnt work for me when i first looked at it. maybe try this instead: ----------------------------------- LIBRARY "x.dll" DESCRIPTION 'x.dll' EXETYPE NT CODE PRELOAD DATA PRELOAD
Jan 31 2008
"Unknown W. Brackets" <unknown simplemachines.org> wrote in message news:fnuiqt$ags$1 digitalmars.com...Thanks. Actually, I have no trouble whatsoever making dlls. I have a problem referencing functions in the program that loaded the DLL.You shouldn't need a .def file at all for this program. In fact, you should be able to compile the app the same way you compile any other app. That it loads a dynamic library at runtime means nothing to the compiler/linker.Ain't Linux better? Oi.DLLs are a pretty awful approximation of SOs, yes.
Feb 01 2008
Well, the def being for the library, not for the program loading the library. Otherwise I don't get exports named properly, etc. -[Unknown] Jarrett Billingsley wrote:"Unknown W. Brackets" <unknown simplemachines.org> wrote in message news:fnuiqt$ags$1 digitalmars.com...Thanks. Actually, I have no trouble whatsoever making dlls. I have a problem referencing functions in the program that loaded the DLL.You shouldn't need a .def file at all for this program. In fact, you should be able to compile the app the same way you compile any other app. That it loads a dynamic library at runtime means nothing to the compiler/linker.Ain't Linux better? Oi.DLLs are a pretty awful approximation of SOs, yes.
Feb 01 2008
"Unknown W. Brackets" <unknown simplemachines.org> wrote in message news:fnvd2q$229m$1 digitalmars.com...Well, the def being for the library, not for the program loading the library. Otherwise I don't get exports named properly, etc.In that case, I'd be more interested to see how you're compiling all this code. The code itself looks very simplistic, and I don't see any apparent failure points.
Feb 01 2008
Okay. Example "plugin" example.d: --- module example; extern (C) export int foo(); version (Windows) import utils.windows; extern (C) export int example() { return 42 + foo(); } --- Compiled with: $(DMD) $(DFLAGS_DEBUG) -op -of$(OUTPUT) $(LIBS) $(wildcard utils/*.d) example.d example.def Or: $(GDMD) $(DFLAGS_DEBUG) -op -of$(OUTPUT) $(LIBS) $(wildcard utils/*.d) example.d -fPIC -q,-rdynamic,-shared Plugin linker definition file: --- LIBRARY example.dll DESCRIPTION 'Example' EXETYPE NT SUBSYSTEM WINDOWS 4.0 CODE PRELOAD SHARED DISCARDABLE DATA PRELOAD SINGLE EXPORTS example --- Example host program for Windows, load_test.d: --- module load_test; import std.c.windows.windows; import std.string, std.stdio; extern (C) alias int function() example_f; int main() { HMODULE m = cast(HMODULE) LoadLibraryA(toStringz("example.dll")); example_f f = cast(example_f) GetProcAddress(m, toStringz("example")); if (f) writefln("%d", f()); FreeLibrary(m); return 0; } extern (C) export int foo() { return 43; } --- Quick DllMain file from samples, utils/windows.d: --- module utils.windows; version (Windows): import std.c.windows.windows; extern (C) { void gc_init(); void gc_term(); void _minit(); void _moduleCtor(); void _moduleUnitTests(); HINSTANCE g_hInst; } extern (Windows) BOOL DllMain(HINSTANCE hInstance, ULONG ulReason, LPVOID pvReserved) { switch (ulReason) { case DLL_PROCESS_ATTACH: gc_init(); // initialize GC _minit(); // initialize module list _moduleCtor(); // run module constructors _moduleUnitTests(); // run module unit tests break; case DLL_PROCESS_DETACH: gc_term(); // shut down GC break; case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: default: // Multiple threads not supported yet return false; } g_hInst = hInstance; return true; } --- I don't have the Linux loader in front of me but it's almost exactly the same and works just fine (LoadLibraryA => dlopen, GetProcAddress => dlsym, FreeLibrary => dlclose, with some dlerror logic in there.) But as stated, it appears that there's really no "reverse linking" of DLLs. -[Unknown] Jarrett Billingsley wrote:"Unknown W. Brackets" <unknown simplemachines.org> wrote in message news:fnvd2q$229m$1 digitalmars.com...Well, the def being for the library, not for the program loading the library. Otherwise I don't get exports named properly, etc.In that case, I'd be more interested to see how you're compiling all this code. The code itself looks very simplistic, and I don't see any apparent failure points.
Feb 01 2008
"Unknown W. Brackets" <unknown simplemachines.org> wrote in message news:fo0p7c$1tbq$1 digitalmars.com...Okay. Example "plugin" example.d: --- module example; extern (C) export int foo();Ohhh, _there_ it is; I think this bit got cut out of the original post :)I don't have the Linux loader in front of me but it's almost exactly the same and works just fine (LoadLibraryA => dlopen, GetProcAddress => dlsym, FreeLibrary => dlclose, with some dlerror logic in there.) But as stated, it appears that there's really no "reverse linking" of DLLs.As in having DLLs link to symbols exported from the app? Right, it's not possible without some hackery. I'm not sure how to do it but apparently it can be done. I think there are restrictions on it, though. DLLs really *are* an awful approximation of SOs :(
Feb 02 2008
"Jarrett Billingsley" <kb3ctd2 yahoo.com> wrote in message news:fo1ufl$11if$1 digitalmars.com..."Unknown W. Brackets" <unknown simplemachines.org> wrote in message news:fo0p7c$1tbq$1 digitalmars.com...As in having DLLs link to symbols exported from the app? Right, it's not possible without some hackery. I'm not sure how to do it but apparently it can be done. I think there are restrictions on it, though. DLLs really *are* an awful approximation of SOs :(However there's hope: DDL. http://www.dsource.org/projects/ddl It's not entirely polished, but it's basically a sort of SO implementation for D on Windows, only it's entirely in userland rather than being part of the OS. Some simple tests have shown that it's more or less able to do the same stuff you can do with SOs. It takes a little more work but the end results are much, much better than DLLs could hope to be :)
Feb 02 2008
Yes, I looked at that and tried it, but I'm afraid I may not have the time right now to port it from Mango to using Tango... Thanks for the help and comments. -[Unknown] Jarrett Billingsley wrote:"Jarrett Billingsley" <kb3ctd2 yahoo.com> wrote in message news:fo1ufl$11if$1 digitalmars.com..."Unknown W. Brackets" <unknown simplemachines.org> wrote in message news:fo0p7c$1tbq$1 digitalmars.com...As in having DLLs link to symbols exported from the app? Right, it's not possible without some hackery. I'm not sure how to do it but apparently it can be done. I think there are restrictions on it, though. DLLs really *are* an awful approximation of SOs :(However there's hope: DDL. http://www.dsource.org/projects/ddl It's not entirely polished, but it's basically a sort of SO implementation for D on Windows, only it's entirely in userland rather than being part of the OS. Some simple tests have shown that it's more or less able to do the same stuff you can do with SOs. It takes a little more work but the end results are much, much better than DLLs could hope to be :)
Feb 02 2008
"Unknown W. Brackets" <unknown simplemachines.org> wrote in message news:fo2i09$280r$1 digitalmars.com...Yes, I looked at that and tried it, but I'm afraid I may not have the time right now to port it from Mango to using Tango...It already uses Tango, and doesn't depend on Mango anymore, AFAIK. I was able to get it installed and working in a couple minutes.
Feb 02 2008
Ah, that's good news. I just did the download, and didn't think to check out the latest trunk. Thanks again. -[Unknown] Jarrett Billingsley wrote:"Unknown W. Brackets" <unknown simplemachines.org> wrote in message news:fo2i09$280r$1 digitalmars.com...Yes, I looked at that and tried it, but I'm afraid I may not have the time right now to port it from Mango to using Tango...It already uses Tango, and doesn't depend on Mango anymore, AFAIK. I was able to get it installed and working in a couple minutes.
Feb 02 2008
Hello again, I dont't suppose you might tell me what revision? I couldn't get the latest trunk to work for me... I was getting the same pointer back from getDExport whether I linked and registered or not. I was trying the host.d and mule.d example files... perhaps I did something wrong? Thanks, -[Unknown] Jarrett Billingsley wrote:"Unknown W. Brackets" <unknown simplemachines.org> wrote in message news:fo2i09$280r$1 digitalmars.com...Yes, I looked at that and tried it, but I'm afraid I may not have the time right now to port it from Mango to using Tango...It already uses Tango, and doesn't depend on Mango anymore, AFAIK. I was able to get it installed and working in a couple minutes.
Feb 04 2008
"Unknown W. Brackets" <unknown simplemachines.org> wrote in message news:fo8t44$2v0j$1 digitalmars.com...Hello again, I dont't suppose you might tell me what revision? I couldn't get the latest trunk to work for me... I was getting the same pointer back from getDExport whether I linked and registered or not. I was trying the host.d and mule.d example files... perhaps I did something wrong?I have 286.
Feb 05 2008
Okay, no love there. What version of Tango are you using with it? Perhaps mine (latest download) is too new. Thanks again. -[Unknown] Jarrett Billingsley wrote:"Unknown W. Brackets" <unknown simplemachines.org> wrote in message news:fo8t44$2v0j$1 digitalmars.com...Hello again, I dont't suppose you might tell me what revision? I couldn't get the latest trunk to work for me... I was getting the same pointer back from getDExport whether I linked and registered or not. I was trying the host.d and mule.d example files... perhaps I did something wrong?I have 286.
Feb 07 2008
"Unknown W. Brackets" <unknown simplemachines.org> wrote in message news:fogp7r$1eas$1 digitalmars.com...Okay, no love there. What version of Tango are you using with it? Perhaps mine (latest download) is too new.The last time I tried it out I think I was using 0.99.3; I'll admit I haven't tried since upgrading to 0.99.4.
Feb 08 2008
Jarrett Billingsley:However there's hope: DDL. http://www.dsource.org/projects/ddlIt looks really nice. Regarding the Quick DDL Tutorial: http://www.dsource.org/projects/ddl/wiki/Tutorial/UsingDDL/Quick I think the interface may be eventually simplified to something like this (it may perform the "dmd -c plugin.d" too if needed): import std.stdio, ddl; void main(){ auto plugin = dlink("plugin.d"); if (plugin.hasFunction("helloWorld")) { auto hello = plugin.Func!(string function(), "helloWorld"); writefln(hello()); } } (Or/and equivalent for Tango). Bye, bearophile
Feb 04 2008
Jarrett Billingsley wrote:"Unknown W. Brackets" <unknown simplemachines.org> wrote in message news:fo0p7c$1tbq$1 digitalmars.com...Ive never had problems resolving an .exe's exported symbols at runtime. Dunno why it would be an issue doing it from inside a DLL. x = GetModuleHandle(NULL); // handle to image that created the process GetProcAddress(x, "foo_"); // or "foo" depending how the compiler generates C symbolsOkay. Example "plugin" example.d: --- module example; extern (C) export int foo();Ohhh, _there_ it is; I think this bit got cut out of the original post :)I don't have the Linux loader in front of me but it's almost exactly the same and works just fine (LoadLibraryA => dlopen, GetProcAddress => dlsym, FreeLibrary => dlclose, with some dlerror logic in there.) But as stated, it appears that there's really no "reverse linking" of DLLs.As in having DLLs link to symbols exported from the app? Right, it's not possible without some hackery. I'm not sure how to do it but apparently it can be done. I think there are restrictions on it, though. DLLs really *are* an awful approximation of SOs :(
Feb 03 2008
I'm not wanting to have to do that from the DLL. Here's a practical example: void plugin_function () { if (ask_host_for_something() != 42) tell_host_about_error("Oh no!"); } I suppose you're suggesting I could either use GetModuleHandle(NULL) by passing it to the plugin, or from within the plugin (unclear but at least it makes this doable, though annoying.) However, even then, .so files are simpler - it sets up the symbols for me. I don't have to GetProcAddress any of them. -[Unknown] Neal Alexander wrote:Jarrett Billingsley wrote:"Unknown W. Brackets" <unknown simplemachines.org> wrote in message news:fo0p7c$1tbq$1 digitalmars.com...Ive never had problems resolving an .exe's exported symbols at runtime. Dunno why it would be an issue doing it from inside a DLL. x = GetModuleHandle(NULL); // handle to image that created the process GetProcAddress(x, "foo_"); // or "foo" depending how the compiler generates C symbolsOkay. Example "plugin" example.d: --- module example; extern (C) export int foo();Ohhh, _there_ it is; I think this bit got cut out of the original post :)I don't have the Linux loader in front of me but it's almost exactly the same and works just fine (LoadLibraryA => dlopen, GetProcAddress => dlsym, FreeLibrary => dlclose, with some dlerror logic in there.) But as stated, it appears that there's really no "reverse linking" of DLLs.As in having DLLs link to symbols exported from the app? Right, it's not possible without some hackery. I'm not sure how to do it but apparently it can be done. I think there are restrictions on it, though. DLLs really *are* an awful approximation of SOs :(
Feb 03 2008
Hm, 1- __declspec(dllimport) int __stdcall foo(); becomes : export extern(Windows) int foo(); so, I would give extern(Windows) instead of extern(C) a try to avoid name mangeling problems. 2- Just guessing : You have module library "DLLMain()" and loader "main()" try to place main() in a seperate file. 3- UNKNOWN WROTE : "I want to dynamically link, and also call functions from the code that is dynamically linking." I can imagine that using callbacks is an interesting option to establish plugings, like : //THE DLL // define the callback function. alias extern(Windows) void function(char* token, size_t siz = 0, bool error =false) DisplayCallBack; export extern(Windows) void ExecuteProcess(DisplayCallBack cb, char* _dir, char* _command, char* _args) { //do someting and call CallBack function defined in Application cb(tok, tok_size) } HTH Bjoern
Feb 01 2008
Unknown W. Brackets Wrote:Consider the following simple "library": --- module library; import loader; // (the DllMain stuff from D's doc pages.) extern (C) export int foo() { return 42 * loader.bar(); } --- And also consider this "application": --- module loader; import std.c.windows.windows; import std.string, std.stdio; extern (C) alias int function() example_f; void main() { HMODULE m = cast(HMODULE) LoadLibraryA(toStringz("library.dll")); example_f f = cast(example_f) GetProcAddress(m, toStringz("foo"));(...) Why did you insert 'extern (C)' in 'library' and 'loader' when you'd like to call D code from D module? getProcAddress takes a decorated name only as a 2nd argument (as you can see in 'Win32 DLLs in D'). Just compile 'library' (or a file containing WinMain that imports it) with -L/map switch to receive a complete symbol list in one *.map file. All the imports are under the "Address Export Alias' section. I've been using an 'Alias' name passed into getProcAddress. [Btw for 'int library.foo()', decorated name alias is _D7library3fooFZi'] Decorated name contains condensed information about module and function names, return type and types of the function args.
Feb 03 2008
This is useless for plugins because I have no idea what the module name will be. It would be ridiculous for me to enforce all plugins use the same module. It might make sense to have an extern (C) export that is the module name, thus enabling me to use such a methodology. But having GetProcAddress("_D7example4initFZi") hard coded in the host would really not work for me. -[Unknown] Tomasz Polachowski wrote:Unknown W. Brackets Wrote:Consider the following simple "library": --- module library; import loader; // (the DllMain stuff from D's doc pages.) extern (C) export int foo() { return 42 * loader.bar(); } --- And also consider this "application": --- module loader; import std.c.windows.windows; import std.string, std.stdio; extern (C) alias int function() example_f; void main() { HMODULE m = cast(HMODULE) LoadLibraryA(toStringz("library.dll")); example_f f = cast(example_f) GetProcAddress(m, toStringz("foo"));(...) Why did you insert 'extern (C)' in 'library' and 'loader' when you'd like to call D code from D module? getProcAddress takes a decorated name only as a 2nd argument (as you can see in 'Win32 DLLs in D'). Just compile 'library' (or a file containing WinMain that imports it) with -L/map switch to receive a complete symbol list in one *.map file. All the imports are under the "Address Export Alias' section. I've been using an 'Alias' name passed into getProcAddress. [Btw for 'int library.foo()', decorated name alias is _D7library3fooFZi'] Decorated name contains condensed information about module and function names, return type and types of the function args.
Feb 03 2008