C ++: implementing class methods in a shared shared library

I believe that I may have an implementation of the parts of the class in a shared lib, as the characters load when used.

myclass.h --- class C { void method(); } main.cpp --- #include "myclass.h" int main() { //dynamically load mylib.so using dlopen/dlsym/dlclose ... C *c = new C(); c->method(); delete c; } mylib.so compiled separately: ==== mylib.cpp --- #include "mylib.h" void C::method() { ... } 

This works great.

However, as soon as I finished using C :: method (), I would like to unload it, so I can change, recompile and reload it without reloading the main program

 int main() { //dynamically load mylib.so using dlopen/dlsym/dlclose ... C *c = new C(); c->method(); delete c; // close the lib, remove the handle... .... char pause; cin << pause; // before carrying on change the C::method, recompile it //dynamically load *Again* mylib.so using dlopen/dlsym/dlclose ... C *c = new C(); c->method(); delete c; } 

The problem is that it does not unload the library when the first dlclose is executed, possibly because there is an instance of my C class. Any way to force this?

(using g ++ 4.2.3, on Linux Ubuntu 10.04)

+7
source share
1 answer

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() { // ... } extern "C" C* createC() { return new D(); } 

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; } 
+9
source

All Articles