[MLton] MLton and shared libraries

Wesley W. Terpstra wesley@terpstra.ca
Wed, 13 Apr 2005 23:46:11 +0200


On Wed, Apr 13, 2005 at 08:33:19AM -0400, Matthew Fluet wrote:
> 1) getting the shared library to initialize the SML heap and
> run all the top-level effects (such as allocating and initializing
> globals) of the program with exported functions,

Just wanted to mention that the symbol '_init' is run on shared libraries
when they are 'dlopen'ed. So, you can plop init code in there if desired.
There's also a '_fini' for when unloaded. Notice that shared linkage also
uses 'dlopen' so linking against such a library still triggers the code.
For executables, '_init' usually calls 'main'

The gotcha is that gcc normally creates these symbols. The -nostartfiles
will avoid this problem, but might cause problems if there's any C++ code 
with static constructors in the library or potentially other cases.

Example:

foo.c:
#include <stdio.h>
void _init() { printf("got opened\n"); }
void _fini() { printf("got closed\n"); }

bah.c:
#include <stdio.h>
void main() { printf("main run\n"); }

$ gcc -shared -nostartfiles -o foo.so foo.c
$ gcc -o bah bah.c foo.so
$ export LD_LIBRARY_PATH=.
$ ./bah
got opened
main run
got closed

Of course, the above only applies to ELF binaries and probably won't work
under windows, though cygwin might be clever enough to translate this.

Another (portable) trick is to include a dash of C++ in the library.
The only quirk is that load order between translation units is unspecified.
However, I can't imagine that this would be a problem calling into C.

foo.cpp:
#include <stdio.h>
struct Init {
  Init() { printf("got opened\n"); }
  ~Init() { printf("got closed\n"); }
};
Init foo;

g++ -shared foo.cpp -o foo.so

Unfortunately, neither of the above tricks works for static linkage.
Personally, I think the C++ trick _SHOULD_ work, but the ld authors don't.
People regularily file bugs against them for this, but they refuse to
fix the issue and instead claim their behaviour is correct.

Probably the best thing to do though, is just to export two methods:
void yourlib_startup(void);
void yourlib_close(void);

-- 
Wesley W. Terpstra