C ++: неопределенные символы при загрузке разделяемой библиотеки с помощью dlopen ()

У меня есть проблема, когда я пытаюсь использовать dlopen () для загрузки общей библиотеки в другую общую библиотеку. Я проверил все уроки о том, как правильно использовать dlopen (). Итак, вот упрощенный код:

Основная разделяемая библиотека содержит класс с чисто виртуальными функциями, которые должна реализовывать вспомогательная разделяемая библиотека (также называемая плагином). Кроме того, он имеет некоторые другие функции, которые реализованы с поведением по умолчанию. Я создал макрос, который добавляется в каждый плагин, чтобы иметь символ для загрузки и создания класса.

Основная общая библиотека

plugin.h:

Class A {
public:
virtual int func1() = 0;
virtual bool func2() const;
}

#define CREATE_CLASS(cls) extern "C" void *CreateClass(void) { return new cls; }

plugin.cpp:

bool A::func2() const {   return true; }

Сборка и ссылка main.so

g++ -g -Wall -Woverloaded-virtual -Wno-parentheses -O2 -fPIC -c -o plugin.o plugin.cpp
g++ -g -Wall -Woverloaded-virtual -Wno-parentheses -O2 -fPIC  -rdynamic -shared plugin.o -ldl -o main-plugin.so

Библиотека общего доступа реализует только чисто виртуальные функции. Другая функция может быть переопределена, хотя и является необязательной.

Sub общая библиотека

плагин-impl.cpp

Class B : public A {
public:
virtual int func1() { return 0; }
}

CREATE_CLASS(B)

Это строки для создания и связывания разделяемой библиотеки.

Сборка и ссылка на sub.so

g++ -g -O3 -Wall -Werror=overloaded-virtual -Wno-parentheses -fPIC -c -o subPlugin.o subPlugin.cpp
g++ -g -O3 -Wall -Werror=overloaded-virtual -Wno-parentheses -fPIC  -shared subPlugin.o  -o subPlugin.so

Это строка для открытия разделяемой библиотеки. Я пытался LAZY, СЕЙЧАС, СЕЙЧАС | GLOBAL и так далее, без каких-либо последствий.

Вызов dlopen () где-нибудь в основной разделяемой библиотеке:

  handle = dlopen(file.c_str(), RTLD_LAZY);

Большая часть этого работает очень хорошо. Тем не менее, когда я пытаюсь загрузить разделяемую библиотеку в основную разделяемую библиотеку, dlopen жалуется на неопределенный символ bool A::func2() const, Функция существует только в основной разделяемой библиотеке, так что, я думаю, ее все равно нужно экспортировать. Пожалуйста, помогите мне! Я очень смущен!

Поскольку я не могу изменить исполняемый файл, я должен связать основную общую библиотеку с подчиненными общими библиотеками, добавив следующие параметры в g ++:

-L$(PLUGINDIR) -Wl,-R$(PLUGINDIR) -lmain-shared

С этим набором не требуется устанавливать LD_LIBRARY_PATH,

2

Решение

Так как вашей суббиблиотеке нужны символы из основной библиотеки, я думаю, вы хотите, чтобы она была связана с ней. Попробуйте связать это так:

g++ -g -O3 -Wall -Werror=overloaded-virtual -Wno-parentheses -fPIC  -shared
-lmain-plugin subPlugin.o  -o subPlugin.so

Возможно, вам нужно будет поиграть с -L также.

Вот что я попробовал:

jirka@debian:/tmp$ cat executable.cpp
#include <dlfcn.h>
#include <stdio.h>
int main()
{
dlopen("./main-library.so", RTLD_NOW);
void* handle=dlopen("./sub-library.so", RTLD_LAZY);
printf("%x %s", dlsym(handle, "CreateClass"), dlerror());
}
jirka@debian:/tmp$ cat main-library.cpp
class A {
public:
virtual int func1() = 0;
virtual bool func2() const;
};

#define CREATE_CLASS(cls) extern "C" void *CreateClass(void) { return new cls; }

bool A::func2() const {   return true; }
jirka@debian:/tmp$ cat sub-library.cpp
class A {
public:
virtual int func1() = 0;
virtual bool func2() const;
};

#define CREATE_CLASS(cls) extern "C" void *CreateClass(void) { return new cls; }

class B : public A {
public:
virtual int func1() { return 0; }
};

CREATE_CLASS(B)

jirka@debian:/tmp$ g++ -g -Wall -Woverloaded-virtual -Wno-parentheses -O2 -fPIC  -rdynamic -shared main-library.cpp -ldl -o main-library.so
jirka@debian:/tmp$ g++ -g -O3 -Wall -Werror=overloaded-virtual -Wno-parentheses -fPIC  -shared -l:main-library.so sub-library.cpp  -o sub-library.so
jirka@debian:/tmp$  g++ -ldl executable.cpp -o executable
jirka@debian:/tmp$ LD_LIBRARY_PATH=. ./executable
b7713740 (null)

Еще одна возможность добавления RTLD_GLOBAL при загрузке main-library:

jirka@debian:/tmp$ cat executable.cpp
#include <dlfcn.h>
#include <stdio.h>
int main()
{
dlopen("./main-library.so", RTLD_LAZY | RTLD_GLOBAL);
void* handle=dlopen("./sub-library.so", RTLD_LAZY);
printf("%x %s", dlsym(handle, "CreateClass"), dlerror());
}

Таким образом, вам не нужно ничего связывать с main-library.so,

3

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]