3

On Windows it is possible to dynamically link to an executable with exported symbols. For example following code:

// main.c
void __declspec(dllexport) interface_function() {}
int main() {}

// ext.c
void interface_function();
void extension_function() {
    interface_function();
}

With

cl.exe main.c
cl.exe ext.c /LD /link main.lib

would produce an executable main.exe, a static library main.lib for implicit linking, and a dynamic library ext.dll.

Similar behavior can be achieved in OSX with shared libraries:

// main.c
void interface_function() {}
int main() {}

// ext.c
void interface_function();
void extension_function() {
    interface_function();
}

With

gcc main.c -o main
gcc ext.c -bundle -bundle_loader main -o ext.bundle

it is virtually equivalent to the Windows setup.

But for dynamiclib:

> gcc ext.c -dynamiclib -o ext.dylib

and shared:

> gcc ext.c -shared -o ext.so

I cannot get them to work because of undefined symbols on one hand and unable to load an executable with -l flag on the other.

I can let them resolve undefined symbols in runtime with -undefined dynamic_lookup. But this is not a sustainable way because all the link errors are now happening in run-time instead.

Is there a way to provide the list of symbols to dynamically load from an executable when linking as -shared and -dynamiclib?

Teivaz
  • 5,462
  • 4
  • 37
  • 75

1 Answers1

1

Yes this is possible, but then you'll want to create a bundle rather than a shared library (see this answer for more detail).

If you have a main application like so:

#include <stdio.h>
#include <dlfcn.h>

int func(void)
{
    return 42;
}

int main(void)
{
    void *dl = dlopen("plugin.so", RTLD_LOCAL);
    if(!dl) return -1;

    int (*derp)(void) = dlsym(dl, "derp");
    if(!derp) return -1;

    printf("derp(): %i\n", derp());

    return 0;
}
clang -o main main.c -Wall -Wl,-export_dynamic

Then you can compile bundles against it like so:

int func(void);

int derp(void)
{
    return -func();
}
clang -o plugin.so plugin.c -Wall -bundle -bundle_loader ./main
Siguza
  • 21,155
  • 6
  • 52
  • 89
  • It seems like you wanted to say "No, this is not possible" because my question is not about bundles. What is the purpose of the `export_dynamic` flag. In my example of bundle everything works without it. – Teivaz May 07 '18 at 07:38
  • From the `ld` man page: "Preserves all global symbols in main executables during LTO. Without this option, Link Time Optimization is allowed to inline and remove global functions. This option is used when a main executable may load a plug-in which requires certain symbols from the main executable." – Siguza May 08 '18 at 12:43
  • that is interesting. I have built test project without this flag and it still managed to link and run. I’ve checked as well on a large qt project and it still works without. – Teivaz May 08 '18 at 13:06
  • 1
    Well, it's specific to LTO. Idk about other platforms, but on macOS that seems disabled by default (can be enabled with `-flto`). If I build my `main.c` with `-flto`, `func` disappears from the symbol table. – Siguza May 08 '18 at 14:40