我有一个问题,当我尝试使用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
子共享库并仅实现纯虚函数。 其他功能可以重写尽管它是可选的。
子共享库
插件,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
这是打开子共享库行。 我想偷懒,现在,现在| 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
。