I'm trying to build a system, that uses dynamic loaded library files (.so files) as plugins in C++14. I build the project using gcc in combination with qt5.5.1 within qtcreator.
The problem I'm having is, that I don't fully understand, what dlopen() (and dlsym()) actually does and get strange behavior because of it. Here is a simplified (not executable) Version:
/*Kernel.hpp*/
class Kernel{
int loadPlugins();
}
void* sharedPointer; //The Object location is stored in here
/*Kernel.cpp*/
Kernel::loadPlugins(){
handle1 = dlopen(<file1>, RTLD_LAZY);
init_t init = (init_t) dlsym(handle1, "init"); //init_t is just a fitting function pointer
execute_t exec = (execute_t) dlsym(handle1, "execute"); //same goes for "execute_t"
handle2 = dlopen(<file2>, RTLD_LAZY);
init_t init = (init_t) dlsym(handle2, "init");
execute_t exec = (execute_t) dlsym(handle2, "execute");
}
/*<file1.h>*/
Class Test{
int func();
int field = 0;
}
/*<file1.cpp>*/
int Test::func(){/*do stuff*/}
Test* test = NULL;
extern void* sharedPtr; //use the ptr from kernel
extern "C" init(){
test = new Test();
sharedPtr = (void*)test; //store address of newly created Test-Object
}
extern "C" execute(){
/* Do Stuff */
}
/*<file2.h>*/
/*<file2.cpp>*/
Test* test = NULL;
extern void* sharedPtr; //use the ptr from kernel
extern "C" init(){
test = (Test*)sharedPtr; //get address of Testobject
}
extern "C" execute(){
std::cout << test->field << std::endl; //Working perfectly
std::cout << test->func() << std::endl //Segmentaion fault
}
The precise Error is a symbol lookup error of a member function with some mangled name (unmangled name is Kernel::test()).
What I think, that should happen: When Kernel.loadPlugins() is called, the first library creates an object, saves its address in the main program. Library reads that address and can use it, as if it had created that object. So the field can be read and written to and the member function can be called.
What actually happens: When Kernel.loadPlugins() is called, the first library creates said object, can use it as expected, saves its address in the main program. Library receives said address as expected, can use the field of said object as expected (it does not matter what type that field has, even other objects, like strings, worked, valgrind does not show any leaks as well), but when it tries to call func() it produces a segmentation fault.
I have two primary doubts - First, I would like to know why that happens? Second, I would like to know if there is a nice way to fix it?