Динамически загружаемая библиотека и глобальные переменные в 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() приводит к ошибке сегментации.

У меня есть два основных сомнения: во-первых, я хотел бы знать, почему это происходит? Во-вторых, я хотел бы знать, есть ли хороший способ это исправить?

0 ответов

Другие вопросы по тегам