Dynamic Class Loading for C++ on Linux

A technique for developers that will provide them with much flexibility in design.

Autoregistration

Loading the maker functions into an array associates a
position in the array with each maker. While this may be useful in
some cases, we can obtain more flexibility using an associative
array to hold the makers. The Standard Template Library (STL)
map class works well for this, as
we can then assign key values to the makers and access them via
these values. For example, we may desire to assign string names to
each class and use these names to invoke the appropriate maker. In
this case, we can create a map such as this:

typedef shape *maker_ptr();
map <string, maker_ptr> factory;

Now when we want to create a particular shape, we can invoke
the proper maker using the shape name:

shape *my_shape = factory[

We can extend this technique to make it even more flexible. Rather
than loading the class makers in and explicitly assigning a key
value to them, why not let the class designers do the work for us?
Using a little bit of ingenuity, we can have the makers register
themselves with the factory automatically, using whatever key value
the class designer chooses. (There are a couple of warnings here.
The key must be of the same type as all the other keys, and the key
value must be unique.)

One way to accomplish this would be to include a function in
each shape library that registers the maker for us, and then call
this function every time we open a shape library. (According to the
dlopen man page, if your library exports a function called
_init, this function will be
executed when the library is opened. This may seem to be the ideal
place to register our maker, but currently the mechanism is broken
on Linux systems. The problem is a conflict with a standard linker
object file, crt.o, which exports a function called _init.) As long
as we are consistent with the name of this function, the mechanism
works well. I prefer to forego that approach in favor of one that
will register the maker simply by opening the library. This
approach is known as “self-registering objects” and was
introduced by Jim Beveridge (see Resources).

We can create a proxy class used solely to register our
maker. The registration occurs in the constructor for the class, so
we need to create only one instance of the proxy class to register
the maker. The prototype for the class is as follows:

class proxy {
public:
proxy(){
factory["shape name"] = maker;
}
};

Here, we assume factory is a global map exported by the main
program. Using
gcc/egcs,
we would be required to link with the rdynamic
option to force the main program to export its symbols to the
libraries loaded with dlopen.

Next, we declare one instance of the proxy:

proxy p;

Now when we open the library, we pass the
RTLD_NOW flag to dlopen, causing
p to be instantiated, thus registering our
maker. If we want to create a circle, we invoke the circle maker
like so:

shape *my_circle = factory["circle"];

The autoregistration process is powerful because it allows us to
design the main program without having explicit knowledge of the
classes we will support. For instance, after the main program
dynamically loads any shape libraries, it could create a shape
selection menu using all the keys registered in the factory. Now
the user can select “circle” from a menu list, and the program
will associate that selection with the proper maker. The main
program does not need any information about the circle class as
long as the class supports the shape API and its maker is properly
defined.

Listings 1 through 5 pull together the concepts presented
thus far. The shape class defined in Listing 1 is the base class
for all shapes. Listings 2 and 3 are the source code for
dynamically loadable libraries that provide circle and square
shapes, respectively.

Listing 4 is the main program that is extensible through
dynamically loaded libraries. It scans the current directory for
any .so files (libraries) and opens them. The libraries then
register their makers with the global factory provided by the main
program. The program then dynamically constructs a menu for the
user with the shape names registered by the libraries. Using the
menu, the user can construct shapes, draw the shapes constructed,
or exit the program. Listing 5 is the makefile used to build the
project.

I've got this pb :
I load dynamically some personal lib as you showed. But some objects of this lib also load some other lib dynamically. Those libs have direct dependencies with the root one , and when I dlopen them, I've got an error telling that dlopen tries to load the root lib (which is not in classical dirs, I loaded it with absolute path) and can't find it.

Great article and easy to follow. This is exactly the sort of information I was looking for. I've previously written a large application in C which used dynamic modules, but I've been digging around to find the "proper" way to do the same thing in C++. This article cut right to the chase.

Hi ! Just wanted to say thanks for the nice article. Just tried it with g++ 4.xx. Works nearly out of the box... If you have more than one "shape" that you want to add, I would add static to the definitions of the maker function and the proxy p. This saves you from renaming it in every file.

I tried to include the above code into our project using automake.
Since i am building the libs in -> src/entities/Makefile.am all the .so files go directly to src/entities/.libs/*.so
when i make a 'make install' the libs go to /usr/local/lib/*.so (or somewhere else)
now if my program in src/program wants to open the libs, it does not know in what path to search (i have to add it by using: dlopen("src/entities/.libs/module.so", RT_NOW);)

Since i think that Automake should provide a facility for the 'searchpath', and i am absolutely unable to find it:
DOES ANYONE know ho to do this??
any help is appreciated

Well, it's work fine for me (Gentoo Linux). But now I've tried to write a programm for a Solaris based system ... and the linker gives me some errors. So there must be a way to get it running, cause the compiler knows the dlopen(), dlsym() methods ... but the linker gives me errors.
Perhaps anybody can give me some hints ?
(Compiler : g++ 3.3)

Oh yeah, almost forgot, you also want to make sure you don't forget to add the -ldl flag as a g++ command line argument. That tells the linker it should load the library you need to execute the dlxxxx series calls.

Wow, this works great, but I did run into one problem. I have a shape class which declares a draw() method. I can dynamically load the circle and square classes (which inherit from shape) and get polymorphic behavior. However, this only works if shape defines draw() as an empty method as opposed to a pure virtual method. If I try to declare draw() as a pure method I get an error during dlopen() that says "undefined symbol: __pure_virtual".

It requires extern "C" functions _init() and _fini() in the library. And in dynamic loader there is a serious bug: if you use any of these functions then global static objects are not constructed (i.e. their constructor is not called) so they are in undefined state.

While most of what you say is applicable to my situation, there is one main assumption that you've used... The base class has to be fixed, and dynamically loaded class has no knowledge of the classes in which it has just been instantiated with.

I found out what the problem is. POSIX requires dlsym to return an object pointer while C++ requres that object pointers cannot be cast into function pointers. (This is because some systems have different pointer sizes for objects and functions.) The following union hack should work.