Loading and unloading shared libraries can be tricky sometimes. The biggest problem is when you use the g++ compiler (as opposed to the gcc compiler) it mangles the symbols in the object file so you can't load them later. Here's a "Hello World!" dynamic library in C++ example for your enjoyment.
First, create the library file, called dynamic.cpp
:
[cpp]
#include <cstdio>
extern "C" void _init();
extern "C" void hello(void);
extern "C" void _fini();
void _init() {
printf("Initialization Phase");
}
void hello(void) {
printf("Hello, Dynamic World!");
}
void _fini() {
printf("Deconstruction Phase");
}
[/cpp]
The _init() and _fini() functions will be called automagically when you load or unload the dynamic module.
You can compile this on the command line (we'll create a Makefile
in a minute):
g++ -fPIC -c dynamic.cpp
ld -shared -o dynamic.so dynamic.o
We first compile the function with g++ first because if we just do the whole thing together it automatically adds tons of other symbols you just don't need, not to mention not allowing you to put your own _init()
and _fini()
functions in. If you're curious, go ahead and try to compile it with the command g++ -fPIC -shared -o dynamic.so dynamic.cpp
—it probably won't work!
Next, we need a program to test it with, and in a fit of creative genius I called it main.cpp
:
[cpp]
#include <cstdio>
#include <cstdlib>
#include <dlfcn.h>
int main() {
void *handle;
void (*hello)(void);
char *error;
handle = dlopen("/path/to/my/dynamic.so", RTLD_LAZY);
if(handle == NULL) {
fprintf(stderr, "Error: open/load error of dynamic.so failed: %s\n", dlerror());
exit(1);
}
hello = (void(*)(void)) dlsym(handle, "hello");
if((error = dlerror()) != NULL) {
fprintf(stderr, "Error: symbol lookup in dynamic.so failed: %s\n", dlerror());
exit(2);
}
hello();
dlclose(handle);
return 0;
}
[/cpp]
Now all we need is a good Makefile
:
# Makefile for dynamic module loading APP = test CC = g++ LD = ld all: $(APP) dynamic.o: dynamic.cpp $(CC) -fPIC -c dynamic.cpp dynamic.so: dynamic.o $(LD) -shared -o dynamic.so dynamic.o $(APP): dynamic.so main.cpp $(CC) -o $(APP) main.cpp -ldl clean: @rm -f *.o *.so $(APP)
I realize I don't explain a lot of this code, but it's not too complicated, so it should be pretty easy to understand if you are familiar with C or C++.
Run-Time Linking of Shared Libraries
It's been some time since I updated this page, but I thought I'd mention the run-time linking of shared libraries option. If you create a shared library as above, and install it somewhere in your /etc/ld.so.conf
path, you can compile and link to the library at run-time. This means you don't have to bother with the dlopen
and dlclose
functions, but the shared library must be available at compile time.
First, create your library a little differently:
ld -shared -o libdynamic.so.1.0 dynamic.o
Then copy it to a nice place like /usr/local/lib
and create some symlinks:
cp libdynamic.so.1.0 /usr/local/lib ln -s /usr/local/lib/libdynamic.so.1.0 /usr/local/lib/libdynamic.so.1 ln -s /usr/local/lib/libdynamic.so.1.0 /usr/local/lib/libdynamic.so
The first ln
command makes this whole business work with the run-time linker, the second makes the syntax -ldynamic
work. Make sure you run ldconfig
as root after you install a new library!
Now when you compile, just add the -ldynamic
to your link command and you'll be ready to go!
[...] ilename.c or the same way with .cpp. For a basic tutorial on how so work , I found it over here. First create a file named dynamic.cppas include extern “C [...]
I'm sorry,
after making the symlinks, how could I compile main into executable?
If you mean run-time linking, it's fairly straight forward. If your shared object file is linked as explained above, all you need to link your main executable program is something like this:
where
libraryName
is the name of your library minus thelib
prefix and the.so.1.0
suffix. In fact, it's pretty much exactly like linking a static .a file into your program.Thanks Scurvy Jake!