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