Tuesday, September 28, 2010

Two-way dynamic linking in C

Building a dynamic library (or shared object lib) on Linux is easy. All you do is compile your code with the -fPIC or -fpic flags then use the -shared flag for the link-step:

gcc -fPIC foo.c -shared -o foo.so

Then you can load the dynamic library in your main program by using dl_open and dl_sym to get any global symbol from the library.

But what if you also want your shared object library to link with symbols in the main program? This might be necessary, for example, if the dynamic module wanted to obtain a key from the main program. It would have to call a routine in main just as main is calling routines in the library. In this case you must instruct the main program also to export its symbols during linking:

gcc main.c -ldl -rdynamic -o main

Then, main, when it loads the shared object lib foo, will enable both foo to call routines in main, and main to call routines in foo.

Here's main.c. You can use the last command above to compile it

#include <dlfcn.h>
#include <stdio.h>
int bar()
{
 printf("dynamic lib called bar\n");
 return 0;
}
int main( int argc, char **argv )
{
 void *handle;
 handle = dlopen( "./foo.so", RTLD_GLOBAL|RTLD_LAZY );
 if ( handle != NULL )
 {
  int (*r)(void);
  int res;
  *(void **)(&r) = dlsym(handle, "foo");
  res = (*r)();
  printf("foo returned %d\n",res );
 }
 else
  printf("failed to open foo.so\n");
}

And foo.c. This compiles with the first command above:

#include <stdio.h>
extern int bar();
int foo()
{
 printf("called foo inside lib\n");
 bar();
 return 0;
}

Then run it by calling main:

./main
called foo inside lib
dynamic lib called bar
foo returned 0