Dynamic Class Loading for C++ on Linux
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.
Today’s modular x86 servers are compute-centric, designed as a least common denominator to support a wide range of IT workloads. Those generic, virtualized IT workloads have much different resource optimization requirements than hyperscale and cloud applications. They have resulted in a “one size fits all” enterprise IT architecture that is not optimized for a specific set of IT workloads, and especially not emerging hyperscale workloads, such as web applications, big data, and object storage. In this report, you will learn how shifting the focus from traditional compute-centric IT architectures to an innovative disaggregated fabric-based architecture can optimize and scale your data center.
Sponsored by AMD
Built-in forensics, incident response, and security with Red Hat Enterprise Linux 6
Every security policy provides guidance and requirements for ensuring adequate protection of information and data, as well as high-level technical and administrative security requirements for a system in a given environment. Traditionally, providing security for a system focuses on the confidentiality of the information on it. However, protecting the data integrity and system and data availability is just as important. For example, when processing United States intelligence information, there are three attributes that require protection: confidentiality, integrity, and availability.
Learn more about catching the bad guy in this free white paper.
Sponsored by DLT Solutions
| Using Salt Stack and Vagrant for Drupal Development | May 20, 2013 |
| Making Linux and Android Get Along (It's Not as Hard as It Sounds) | May 16, 2013 |
| Drupal Is a Framework: Why Everyone Needs to Understand This | May 15, 2013 |
| Home, My Backup Data Center | May 13, 2013 |
| Non-Linux FOSS: Seashore | May 10, 2013 |
| Trying to Tame the Tablet | May 08, 2013 |
- Using Salt Stack and Vagrant for Drupal Development
- Making Linux and Android Get Along (It's Not as Hard as It Sounds)
- New Products
- Validate an E-Mail Address with PHP, the Right Way
- Drupal Is a Framework: Why Everyone Needs to Understand This
- A Topic for Discussion - Open Source Feature-Richness?
- The Pari Package On Linux
- Home, My Backup Data Center
- New Products
- Dart: a New Web Programming Experience
- This is the easiest tutorial
5 hours 2 min ago - Ahh, the Koolaid.
10 hours 40 min ago - git-annex assistant
16 hours 40 min ago - direct cable connection
17 hours 2 min ago - Agreed on AirDroid. With my
17 hours 13 min ago - I just learned this
17 hours 17 min ago - enterprise
17 hours 47 min ago - not living upto the mobile revolution
20 hours 38 min ago - Deceptive Advertising and
21 hours 14 min ago - Let\'s declare that you have
21 hours 15 min ago
Enter to Win an Adafruit Prototyping Pi Plate Kit for Raspberry Pi

It's Raspberry Pi month at Linux Journal. Each week in May, Adafruit will be giving away a Pi-related prize to a lucky, randomly drawn LJ reader. Winners will be announced weekly.
Fill out the fields below to enter to win this week's prize-- a Prototyping Pi Plate Kit for Raspberry Pi.
Congratulations to our winners so far:
- 5-8-13, Pi Starter Pack: Jack Davis
- 5-15-13, Pi Model B 512MB RAM: Patrick Dunn
- Next winner announced on 5-21-13!
Free Webinar: Linux Backup and Recovery
Most companies incorporate backup procedures for critical data, which can be restored quickly if a loss occurs. However, fewer companies are prepared for catastrophic system failures, in which they lose all data, the entire operating system, applications, settings, patches and more, reducing their system(s) to “bare metal.” After all, before data can be restored to a system, there must be a system to restore it to.
In this one hour webinar, learn how to enhance your existing backup strategies for better disaster recovery preparedness using Storix System Backup Administrator (SBAdmin), a highly flexible bare-metal recovery solution for UNIX and Linux systems.




Comments
dependencies
And what about depencies of dynamically loaded libs ?
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.
please if someone can help.
hi... i need to create the
hi... i need to create the member variables in a class at runtime... also these variables should be defined by a config file... is it possible .. can anyone help ...
You mean shape *my_circle
You mean
shape *my_circle = factory["circle"]();
rather than
shape *my_circle = factory["circle"];
Nice article. :-)
Cpp
A very good finding for me. I developed a good amount of code in C but i'm new to cpp. I feel familiar with the dynamic libraries in cpp now. ThanQ.
Very useful
This article was perfect, for not just learning basic dynamic module loading, but also the clever, clean technique for autoregistration. Everything worked beautifully for my project right away
Thank you for the article
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.
Nice Article
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.
It's all so wrong
Factories, functions to access libraries, classes with textual names at runtime
It's all so wrong
C++ ! !
YECCCH !
I feel soiled just reading about it
And I feel dumber for having
And I feel dumber for having read your comment. :-(
very constructive comment!
probably from a .net zealot!
I actually like this article if only for the learning experience.
usage with Automake
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
Anybody could provide a
Anybody could provide a working Makefile?, I can not understand how such a nice article can have this Makefile...
Makefile: You have to type
Makefile: You have to type for each '=>'. Save this file as Makefile and run with make.
CC = g++
LIBS = -ldl
.cc.o:
=>$(CC) -ggdb -c $<
default:
=>make main
OBJS = testdcl.o
main: main.o
=>$(CC) -rdynamic -o main main.o $(LIBS)
libcircle.so: circle.o
=>g++ -shared -Wl,-soname,libcircle.so -o libcircle.so circle.o
libsquare.so: square.o
=>g++ -shared -Wl,-soname,libsquare.so -o libsquare.so square.o
all: main libcircle.so libsquare.so
clean:
=>rm -f *.so *.o main
management of vtable
Hi,
I just want to know the how does this manages the vtable after laoding the class dynamically ?
Re: Dynamic Class Loading for C++ on Linux
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)
Cross-platform loading of libraries.
Is there any library that I can use to dynamically load C-libraries on LINUX and WINDOWs both?
I tried Libtool's libltdl library, but it doesnt seem to work on WINDOWS (VC++).
Re: Cross-platform loading of libraries.
Eh? Windows has LoadLibrary() and GetProcAddress() which are nearly identical to dlopen() and dlsym() respectively.
Just make simple proxy functions that will use whichever method is appropriate for the proform it was compiled on.
Pseudo code:
LoadDynamicLibrary(char *path)
{
#ifdef _WIN32
LoadLibrary(path);
#else
dlopen(path);
#endif
}
can you create an object (of
can you create an object (of a class in the dll) using GetProcAddress? pls help...
Re: Cross-platform loading of libraries.
If you're writing a Qt application, you have the QLibrary class that OS independent resolves symbols from .so's resp. .dll's.
Re: Dynamic Class Loading for C++ on Linux
FYI you cannot throw, with ELF/linux under gcc 3.2.3, within the autoregistration proxy class constructor. So your constructor, as in the above example, is implicitly:
class proxy {
public:
proxy() throw() {
factory["shape name"] = maker;
}
};
Re: Dynamic Class Loading for C++ on Linux
It's a good article!!
I can compile your codes wih gcc-2.96 (rh7.2), but no luck with gcc-3.2. I'm a newbir on C++. So, can you make a version that can be compiled with gcc-3.2.
Thx
Re: Dynamic Class Loading for C++ on Linux
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.
Cheers,
tundog
Re: Dynamic Class Loading for C++ on Linux
I had some trouble using gcc-3.2 as well. I couldn't get it to work with the static_cast syntax.
Instead of:
shape *my_shape = static_cast(mkr)();
Try using:
shape *my_shape = ((shape*(*)())(mkr))();
Cheers,
tundog
You can use reinterpret_cast
You can use reinterpret_cast instead of static_cast. This works for me.
Re: Dynamic Class Loading for C++ on Linux
XPLC does all of this, faster, better, simpler, safer.
http://xplc.sourceforge.net/
xplc is 0.3.0 Alpha
I presume that's why more stable is missing on your list of properties...
Re: xplc is 0.3.0 Alpha
Well, this is just some dlopen() sample code in an article, it's not like it's exactly a solid framework either...
Re: Dynamic Class Loading for C++ on Linux
bull***** it does.. lol
Re: Dynamic Class Loading for C++ on Linux
Is there any particular reason why deleting objects is omitted?
Re: Dynamic Class Loading for C++ on Linux
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".
Is there a way I can get around this?
Thanks
Re: Dynamic Class Loading for C++ on Linux
That factory is nice idea but there are some problems with it:
Re: Dynamic Class Loading for C++ on Linux
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.
Re: Dynamic Class Loading for C++ on Linux
#######################
Error while executing the above program of shape :::
In function `int main ()':
m.C:22: cannot dynamic_cast `mkr' (of type `void *') to type `class
shape *' (source is not a pointer to class)
Can any one help me ????
I found out what the problem
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.
template<class TYPE>
TYPE function_cast(void * symbol)
{
assert(sizeof(void *) == sizeof(TYPE));
union
{
void * symbol;
TYPE function;
} cast;
cast.symbol = symbol;
return cast.function;
}
Then you should be able to cast to any pointer-to-function type, for exampe:
shape * my_shape = function_cast<shape(*)()>(mkr)();
A minor correction:
A minor correction:
shape * my_shape = function_cast(mkr)();
A correction of my
A correction of my correction:
shape * my_shape = function_cast(mkr)();
Re: Dynamic Class Loading for C++ on Linux
Hi,
You can try this way :
shape *(*mkr)()= (shape*(*)())dlsym(dlib, "maker");
shape *my_shape = (*mkr)();
my_shape->draw();
Re: Dynamic Class Loading for C++ on Linux
I too had alot of trouble getting this to compile. So I got the mini-dlopen example to work. Then, I came back to this one and it worked immediately after I re-downloaded it. So keep persevering!
Re: Dynamic Class Loading for C++ on Linux
Yes.
it sounds like your compiler is interpreting this line:
shape *my_shape = static_cast(mkr)();
as "cast 'mkr' to 'class shape *' " which is indeed wrong.
you want to cast 'mkr', which is of type pointer-to-function-returning-void*, to type pointer-to-function-returning-shape*, then call it.
Perhaps extracting the function pointer types out to typedefs would help you/the compiler clarify what is needed.
Or maybe just calling mkr(), then casting the returned pointer from void* to shape* would work equally well?
hth,
paulmg
Re: Dynamic Class Loading for C++ on Linux
#######################
Error while executing the above program of shape :::
In function `int main ()':
m.C:22: cannot dynamic_cast `mkr' (of type `void *') to type `class
shape *' (source is not a pointer to class)
Re: Dynamic Class Loading for C++ on Linux
I believe there is a missing
"pclose(dl);" statement.
No big deal.. but running this 'pluggin' framework,
in a loop causes a memory leak then.
Kind Regards,
Unk
--
http://www.triple-it.nl
Re: Dynamic Class Loading for C++ on Linux
I would also replace the command with
dlib = dlopen(name, RTLD_NOW);
by
dlib = dlopen(name, RTLD_NOW|RTLD_GLOBAL);
So symbols from one Shared Library Object file are avaible
to an other Shared Library Object file.
Unk
--
http://www.triple-it.nl/
Re: Dynamic Class Loading for C++ on Linux
I forget to mention that you should rename all the
maker() and proxy-class names.. to prevent name-clashes. (Otherwise you instantiate wrong classes)
Kind Regards,
Unk
--
http://www.triple-it.nl/