C++ class objects and dynamic loading: |
C++ and name mangling:
When running the above "C" examples with the "C++" compiler one will quickly find that "C++" function names get mangled and thus will not work unless the function definitions are protected with extern "C"{}.
- Note that the following are not equivalent:
extern "C"
{
int functionx();
}
| extern "C" int functionx();
|
The following are equivalent:
extern "C"
{
extern int functionx();
}
| extern "C" int functionx();
|
Dynamic loading of C++ classes:
The dynamic library loading routines enable the programmer to load "C" functions. In C++ we would like to load class member functions. In fact the entire class may be in the library and we may want to load and have access to the entire object and all of its member functions. Do this by passing a "C" class factory function which instantiates the class.
The class ".h" file:class Abc {
...
...
};
// Class factory "C" functions
typedef Abc* create_t;
typedef void destroy_t(Abc*);
|
The class ".cpp" file:
Abc::Abc()
{
...
}
extern "C"
{
// These two "C" functions manage the creation and destruction of the class Abc
Abc* create()
{
return new Abc;
}
void destroy(Abc* p)
{
delete p; // Can use a base class or derived class pointer here
}
}
|
This file is the source to the library. The "C" functions to instantiate (create) and destroy a class defined in the dynamically loaded library where "Abc" is the C++ class.
Main executable which calls the loadable libraries:
// load the symbols
create_t* create_abc = (create_t*) dlsym(lib_handle, "create");
...
...
destroy_t* destroy_abc = (destroy_t*) dlsym(lib_handle, "destroy");
...
...
|
Pitfalls:
- The new/delete of the C++ class should both be provided by the executable or the library but not split. This is so that there is no surprise if one overloads new/delete in one or the other.