Динамически загружаемая библиотека и глобальные переменные в C++
Я пытаюсь построить систему, которая использует динамически загружаемые библиотечные файлы (.so файлы) в качестве плагинов в C++14. Я строю проект, используя gcc в сочетании с qt5.5.1 внутри qtcreator.
Проблема в том, что я не до конца понимаю, что на самом деле делает dlopen() (и dlsym()) и из-за этого ведет себя странно. Вот упрощенная (не исполняемая) версия:
/*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
}
Точная Ошибка - это ошибка поиска символа для функции-члена с некоторым искаженным именем (непостоянное имя - Kernel::test()).
Я думаю, что это должно произойти: когда Kernel.loadPlugins() вызывается, первая библиотека создает объект, сохраняет его адрес в основной программе. Библиотека читает этот адрес и может использовать его, как если бы он создал этот объект. Таким образом, поле может быть прочитано и записано, а функция-член может быть вызвана.
Что на самом деле происходит: когда вызывается Kernel.loadPlugins(), первая библиотека создает указанный объект, может использовать его, как и ожидалось, сохраняет свой адрес в основной программе. Библиотека получает указанный адрес должным образом, может использовать поле указанного объекта ожидаемым образом (не имеет значения, какой тип у этого поля, даже другие объекты, такие как строки, работали, valgrind также не показывает утечек), но когда она пытается вызов функции func() приводит к ошибке сегментации.
У меня есть два основных сомнения: во-первых, я хотел бы знать, почему это происходит? Во-вторых, я хотел бы знать, есть ли хороший способ это исправить?