У меня есть проблема, когда я пытаюсь использовать 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
,
Так как вашей суббиблиотеке нужны символы из основной библиотеки, я думаю, вы хотите, чтобы она была связана с ней. Попробуйте связать это так:
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
,
Других решений пока нет …