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