C/C++ Dynamic Libraries and Linux
Posted in
First dog watch, 1 bell (4:37 pm)

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:

#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");
}

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:

#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;
}

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 dlopenand 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!

4 Comments »

4 Responses to “C/C++ Dynamic Libraries and Linux”

  1. [...] 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&#8 [...]

  2. hasrul says:

    I'm sorry,
    after making the symlinks, how could I compile main into executable?

  3. Scurvy Jake says:

    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:

    g++ -o myExecutable main.o -llibraryName
    

    where libraryName is the name of your library minus the lib prefix and the .so.1.0 suffix. In fact, it's pretty much exactly like linking a static .a file into your program.

  4. wsn says:

    Thanks Scurvy Jake!

Leave a Reply