Short answer
It will not work the way you do it. There may also be other problems with your approach that have not yet bit you.
Why it does not work
Undefined characters in your program / library are allowed at different times. On most systems, data references (global variables, vtables class, etc.) are always allowed when loading your program / library. Code references are permitted when they are first used on some systems ("lazy search", at least on Linux and Mac OS X), if some special parameters are not set (RTLD_NOW parameter for dlopen or LD_BIND_NOW environment variable). Once they are fixed, a new search will not be performed.
If you dlopen
your library with the RTLD_GLOBAL flag before the lazy method search is performed, the method from your library will be used. The method method reference is now resolved; he will not change again. Now your main program officially uses the symbols from your dlopen
ed library, so dlclose
will no longer close the library - dlclose
removes only your explicit descriptor.
In short, you should only expect to unload libraries that you use only through explicit dlsym
calls.
What to do instead
Instead, you can provide the library with an implementation of the derived class. You define your C
class as an abstract base class:
class C { public: virtual void method(); };
In your separately compiled library, you must define a derived class and a function that creates an object of this derived class:
class D : public C { public: virtual void method(); }; void D::method() {
Now, in your main program, you have to load the library using dlopen
, get a pointer to createD
with dlsym
and call it to get the object. When all the objects disappear, you can call dlclose
, recompile your library, and repeat everything:
typedef C* (*creatorFunction)(); int main() { for(;;) { void *handle = dlopen("mylib.so", 0); creatorFunction create = (creatorFunction) dlsym(handle, "createC"); C *c = (*create)(); c->method(); delete c; dlclose(handle); char pause; cin << pause; } return 0; }