-
-
Notifications
You must be signed in to change notification settings - Fork 421
Conversation
module main;
import core.runtime, core.thread;
void main() {
auto lib = Runtime.loadLibrary("./liba.so");
auto thr = new Thread({
auto lib = Runtime.loadLibrary("./liba.so");
Runtime.unloadLibrary(lib);
});
thr.start();
thr.join();
Runtime.unloadLibrary(lib);
}module liba;
import std.stdio;
shared static this() { writeln("shared static this()"); }
shared static ~this() { writeln("shared static ~this()"); }
static this() { writeln("static this()"); }
static ~this() { writeln("static ~this()"); }output |
|
Does it work for loading a D dll from C code? |
| } | ||
| .dlclose(handle); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The problem with calling dlclose() here is that the libdl.a needs to be linked in to the D program to access the dlxxxx() functions. This is annoying for normal D programs. The solution is to move the functions that call the dlxxxx() functions into a separate module, hence a D program won't need to link in libdl.a unless it actually tries to dynamically load a DLL.
Alternatively, libdl.so could itself be dynamically loaded as required.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, I fixed this in b44e958.
Now only the shared druntime actually implements rt_loadLibrary/rt_unloadLibrary and some other functions. Calling Runtime.loadLibrary/Runtime.unloadLibrary when linking against a static druntime will lead to a linker error.
Yes, that will work too. |
But what if you statically link with libphobos2.so, and then want to dynamically load a DLL? |
You can see it in posix.mak, libdruntimeso.a is build with DLL support but libdruntime.a is build without, |
|
I updated and finished the low-level implementation. There is an extra layer of thread local reference accounting over the global one in the runtime linker which has some implications on how to use shared libraries.
Finding the dependencies of a library is somewhat expensive so it is only performed for D libraries and non-recursively.
I will try to fix any arising bugs ASAP but I don't have much time left currently. Work on the high-level interface will start around the end of next week. |
Is it still possible to build a plugin for a C application which only uses dlopen? |
| { | ||
| import rt.sections; | ||
| auto libs = pinLoadedLibraries(); | ||
| auto ps = cast(void**).malloc(2 * size_t.sizeof); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we do some explicit error handling (throwing OutofMemoryError, etc)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
|
It was and will remain possible to do that with the static phobos, given that the plugins don't interact (ODR issues). |
- implement rt_loadLibrary/rt_unloadLibrary in src/rt/sections_linux.d - keep hashmap from link_map* to DSO* structs to gather library dependencies and perform thread initialization - thread local reference count to trigger TLS ctors/dtors - add core.thread interface to inherit loaded libraries when spawning a new Thread - make dynamic loading functions only available for version (Shared) - set -version=Shared when building a shared druntime - loading a shared library when statically linking against druntime will cause a link error - Runtime.loadLibrary and Runtime.unloadLibrary are templated so that they are only linked when actually used - the static libphobos2.a does not depends on libdl
- test EH, GC, init/fini and ModuleInfos for linked and loaded D libraries
- linkD - links a D library - loadD - links druntime, loads a D library - loadDR - loads druntime, loads a D library
And done. |
|
Awesome! |
|
Please, Martin, whatever you do, please be sure to archive your explanations from this and other comment threads in a suitable form, even if it's only copying and pasting them to a Wiki page. |
| @@ -169,7 +169,7 @@ struct Runtime | |||
| * Returns: | |||
| * A reference to the library or null on error. | |||
| */ | |||
| static void* loadLibrary( in char[] name ) | |||
| static void* loadLibrary()(in char[] name) | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess a comment should be added that the function is a template on purpose to avoid having to pull in the symbol from the druntime lib. It might not be so obvious for new users/contributors.
I reposted this in the newsgroup but we need better documentation/articles/tutorials. |
|
This PR introduced a regression (linker error on OSX): https://issues.dlang.org/show_bug.cgi?id=20587 |
This still lacks thorough testing so there are likely some bugs but it supports
almost all dynamic loading scenarios, including loading shared libraries in different threads.
depends on #587, #589, #590, #591 and #592