Equivalent of DllMain for OSX dynamic libraries?

Martin Nowak via Digitalmars-d digitalmars-d at puremagic.com
Tue Jul 29 15:52:06 PDT 2014


On 07/26/2014 12:15 AM, Andrei Alexandrescu wrote:
> Hello,
>
>
> We've just open-sourced another D project at Facebook (just a developer
> beta), an ODBC driver for the Presto database engine:
> https://github.com/prestodb/presto-odbc.
>
> The Windows version works well now, and Mark Isaacson (the author of the
> driver and incidentally my intern) is working already on the OSX port
> using iODBC. We've hit a number of issues, the most basic one being that
> shared static this() initializers don't seem to be called for our driver.
>
> Could you folks help us out?
>
>
> Thanks,
>
> Andrei

So this is a statically linked shared D library with a C interface, 
right? This is the only kind of shared libraries currently supported on 
OSX. It means that each lib comes with it's own private copy of 
phobos/druntime, so you got to be careful to not run into ODR issues 
(https://issues.dlang.org/show_bug.cgi?id=7020).

Short answer:

Load the library, get the address of rt_init and call it from your C 
program.

Long answer:

It's a bad practice to automatically initialize dynamic libraries during 
loading because it can lead to deadlocks (on the runtime loader lock). 
Also loading/unloading is globally synchronized and you don't want to 
perform long-running computations while holding the loader lock.

The common pattern is to provide init/fini functions in your library 
which are explicitly called by a user. So you should add 
presto_init/presto_fini functions and call 
Runtime.initialize()/Runtime.finalize() within those functions.
When the C program loads your library it will have to call presto_init 
before using it and presto_fini before unloading it.
Here is an example of this pattern 
https://github.com/D-Programming-Language/druntime/blob/dc559c3ef2916102c6f295d70c3941644e545bf2/test/shared/src/host.c.

If you absolutely need automatic initialization, you can add a C file 
with constructor/destructor functions to your project.

extern void rt_init();
extern void rt_term();

void presto_init() __attribute__((constructor));
void presto_init()
{
   rt_init();
   //...
}

void presto_fini() __attribute__((destructor));
void presto_fini()
{
   //...
   rt_term();
}

The runtime linker will call those functions during loading/unloading.
But once again, we went with explicit initialization because implicit 
init/fini didn't work out too well 
(https://issues.dlang.org/show_bug.cgi?id=11378).


More information about the Digitalmars-d mailing list