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