Desperately looking for a work-around to load and unload D shared libraries from C on OSX

bitwise via Digitalmars-d digitalmars-d at puremagic.com
Thu Sep 17 01:09:52 PDT 2015


On Thursday, 17 September 2015 at 06:40:56 UTC, ponce wrote:
> 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.

Unfortunately, this is a complex problem and you can't just flip 
a few switches and make it work.

> 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.

Calling dlopen won't initialize the runtime in the shared 
library. Although your program doesn't crash, you may find that 
it does once you start calling into the shared lib... or it may 
leak memory because the GC was never initialized. You can call 
Runtime.initialize() from druntime yourself, but as you know, 
there is the callback issue.

I think LDC may be farther along in terms of shared library 
support. You may want to ask David Nadlinger about this. I think 
the problem with LDC was that it only supported statically loaded 
shared libs for osx. I'm not sure if this is still the case, but 
it looks like it:

https://github.com/ldc-developers/druntime/blob/002d0aed65cd24dfcbbc782d9aed2f9112f27b4e/src/rt/sections_ldc.d#L372

>> 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.

I don't think there is any way around this beside building a 
custom runtime and implementing the function I suggested.

> 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.

As a last resort, you may be able to use OSX Distributed Objects, 
depending on what your shared library does. This is basically a 
wrapper around linux pipes, but with a simple RPC-like interface. 
Depending on how much talk there is between the host program and 
your shared lib, this may or may not be a good solution.

https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/DistrObjects/DistrObjects.html

Basically, you would make an Objective-C shared library with a C 
interface, into which the host program could call. This shared 
library would then spawn a second process as needed, which would 
load the D shared library. You would then use distributed objects 
to call from the Objective-C shared library to the D shared 
library. When you were done with the D shared library, you would 
simply terminate the second process.

    Bit





More information about the Digitalmars-d mailing list