Desperately looking for a work-around to load and unload D shared libraries from C on OSX
ponce via Digitalmars-d
digitalmars-d at puremagic.com
Wed Sep 16 23:40:53 PDT 2015
On Wednesday, 16 September 2015 at 23:24:29 UTC, bitwise wrote:
>
> I was trying to solve this one myself, but the modifications to
> DMD's backend that are needed are out of reach for me right now.
>
> If you're willing to build your own druntime, you may be able
> to get by.
I'd prefer a solution that works with existing compilers, but
maybe building a custom LDC is possible if I figure it out.
> If I understand correctly, you want to repeatedly load/unload
> the same shared library, correct? I ask because druntime for
> osx only supports loading a single image at a time:
>
> https://github.com/D-Programming-Language/druntime/blob/1e25749cd01ad08dc08319a3853fbe86356c3e62/src/rt/sections_osx.d#L26
>
In practive I've found that the D shared libraries I produce can
be dlopen/dlclose any number of times, simultaneous too. Using
both LDC and DMD, don't know why it works.
The thing that doesn't work is the C host program dlopen'ing the
shared library, dlclose it, then dlopen another shared library
written in C.
> Anyways, when main() of a D program runs, it calls rt_init()
> and rt_term(). If you don't have a D entry point in your
> program, you have to retrieve these from your shared lib(which
> has druntime statically linked) using dlsym() and call them
> yourself.
I don't control the host program. My shared libs do have an
entrypoint, from which I call Runtime.initialize().
I can also use LDC global constructor/destructor to call
Runtime.initialize / Runtime.terminate, but it doesn't work any
better because of the callback.
>
> https://github.com/D-Programming-Language/druntime/blob/478b6c5354470bc70e688c45821eea71b766e70d/src/rt/dmain2.d#L158
>
> Now, initSections() and finiSections() are responsible for
> setting up the image. If you look at initSections(), the
> function "_dyld_register_func_for_add_image" is the one that
> causes the crash, because there is no way to remove the
> callback, which will reside in your shared lib.
>
> https://github.com/D-Programming-Language/druntime/blob/1e25749cd01ad08dc08319a3853fbe86356c3e62/src/rt/sections_osx.d#L76
>
> So what happens is, when you call
> _dyld_register_func_for_add_image, dyld will call your callback
> for every shared-library/image(including the main application's
> image) that is currently loaded. However, you can skip the
> callback and just call "sections_osx_onAddImage" yourself.
>
> You would have to add something like this to sections_osx.d,
> and call it instead of adding the callback:
>
> void callOnAddImage()
> {
> // dladdr() should give you information about the
> // shared lib in which the symbol you pass resides.
> // Passing the address of this function should work.
> Dl_info info;
> int ret = dladdr(cast(void*)&callOnAddImage, &info);
> assert(ret);
>
> // "dli_fbase" is actually a pointer to
> // the mach_header for the shared library.
> // once you have the mach_header, you can
> // also retrieve the image slide, and finally
> // call sections_osx_onAddImage().
> mach_header* header = cast(mach_header*)info.dli_fbase;
> intptr_t slide = _dyld_get_image_slide(header);
> sections_osx_onAddImage(header, slide);
> }
>
> Now, if you look at finiSections(), it seems to be incomplete.
> There is nothing like sections_osx_onRemoveImage, so you'll
> have to complete it to make sure the library is unloaded
> correctly:
>
> https://github.com/D-Programming-Language/druntime/blob/1e25749cd01ad08dc08319a3853fbe86356c3e62/src/rt/sections_osx.d#L83
>
> You'll may have to make other mods here and there to get this
> working correctly, but this is the bulk of it.
>
> Bit
Thanks for your answer. This is really helpful, though I don't
understand the first thing about what images, headers and
sections are in this context.
More information about the Digitalmars-d
mailing list