Shane Dawalt wrote:
I want to create an application that has modules. Whenever I wish to
expand it, I simply create another module. I don't want to have to
recompile the blasted application.
This led me to thinking about shared libraries. My idea is to create
any number of shared libraries, each being a "module." (A module
contains a single class.) I drop the .so file into a special directory
that my app looks at for shared library files. My app loads each
"module" it finds at startup. Each module provides a well-known function
which my main app calls to get an idea of what the module can do. My
app then instances the proper class from one of the modules and
continues on from there.
First, is there any complete information on how to really create and
use share libraries?
Second, does this description sound even reasonable for the use of
shared libraries?
If not, can someone point me at something that is reasonable for
on-the-fly module loading?
well, a shared library is not much different from any static form of a
library or object file, except that it is linked with the -shared option.
If I am on the right track, then I've been successful at creating the
shared library. I know I must use dlopen(). But I cannot understand
what dlsym() is suppose to be used for. And, how would I specify to
dlsym() the constructor of my class that's in the shared library? I
cannot fathom what its symbol's string representation might be. (I'm
using gcc 3.2.3 if it makes any difference.)
dlopen() opens the object file, meaning, that it allows you to read from
it. However, it does not give you access to a special symbol inside of
this object file yet.
This is what you use dlsym() for. dlsym() returns a pointer to the
correct symbol (e.g. in your case the function). Now this is a bit of a
bugger, as your program cannot know the module's name and constructor, etc.
That's why one way to solve this, is to implement a registration
function, e.g. module_init() inside of your shared object, which will
somehow give your program access to the module.
So if you have something like this:
class module_table{
public:
register_constructor(std::string name, void* fct);
}
then your module_init() function would look like
void module_init(module_table *theTable){
theTable->register_constructor("myName", myConstructor);
}
or similar measures, if your using an object factory to create instances
of your module.
You can also have this registration done by dlopen(), using either _init
and _fini (deprecated according to my dlopen()(3) manpage, or something
like a __attribute__(constructor) function. - However, I don't know what
this is...
Hope, that helped.
Cheers,
Andreas