views:

30

answers:

2

Hello.

I am writing an executable which uses dlopen() (LoadLibrary() on Windows) to dynamically load a shared library. The shared library uses symbols from the executable.

In Windows this is possible. Executables can export symbols: declspec(dllexport) and .def files both work. The linker, when creating the .exe, also creates the .lib file (the "import library"), so the DLL just needs to link with that .lib.

In Linux, this is possible as well. I pass -Wl,-export_dynamic when building the executable so it exports its symbols.

On Mac OS X, instead... -Wl,-export_dynamic does not work, but there is -Wl,-exported_symbols_list,<filename> where <filename> is a list of symbols to export (a sort of a simpler version of a .def file). But then, building the shared library is not as easy: the linker complains about the unresolved symbols.

I tried a hack: renamed the executable to lib<executable>.dylib and, when linking the shared library, I passed -l<executable>. But it gives the error "can't link with a main executable".

The general problem is that Linux shared libraries can have unresolved symbols, while Windows and Mac OS X do not allow it. But Windows has "import libraries" to resolve symbols against dependencies, and Mac OS X apparently does not...

How can this be solved on Mac OS X? Is there an equivalent of an "import library" (the stub library created by the Windows linker when creating a .dll, so, if any module needs to dynamically link to the .dll, it is linked against the "import library")? Or some other solution?

A: 

The standalone Lua interpreter supports dynamically loading (via dlopen) of shared libraries that use symbols from the executable (the Lua API). No special link flag is used when building it. The shared libraries are built using this incantation:

env MACOSX_DEPLOYMENT_TARGET=10.3 gcc -bundle -undefined dynamic_lookup -o random.so lrandom.o
lhf
A: 

Thank you, your answer stimulated the desire to investigate the difference between bundles and dylibs. And ld's manual page mentioned an option called -bundle_loader

-bundle_loader executable
This specifies the executable that will be loading the bundle output file being linked. Undefined symbols from the bundle are checked against the specified executable like it was one of the dynamic libraries the bundle was linked with.

(note that -bundle_loader fails when building a dylib, it only works with bundles) So the old command line

cc -shared -o <output>.so <input>.c

was turned into

cc -bundle -bundle_loader <executable> -o <output>.so <input>.c

and the output bundle resolved its undefined symbols against the executable's.