C ++:使用dlopen()加载共享库时未定义的符号 [英] C++: Undefined symbols when loading shared library with dlopen()
问题描述
我尝试使用dlopen()将共享库加载到另一个共享库时遇到问题。我检查了所有的教程,如何正确使用dlopen()。所以这里是简化的代码:
主共享库包含一个具有纯虚函数的类,子共享库(aka插件)必须实现该类。此外,它具有一些其他功能,它们以默认行为实现。
主共享库 p>
plugin.h:
{
public:
virtual int func1()= 0;
virtual bool func2()const;
}
#define CREATE_CLASS(cls)externCvoid * 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
子共享库只实现纯虚函数。
子共享库
plugin-impl.cpp
B类:public A {
public:
virtual int func1(){return 0; }
}
CREATE_CLASS(B)
$ b
构建并链接sub.so b
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()调用主共享库中的某处: b
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(./ sublibrary.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)externCvoid * 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)externCvoid * 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 sublibrary.so
jirka @ debian:/ tmp $ g ++ -ldl executable.cpp -o executable
jirka @ debian:/ tmp $ LD_LIBRARY_PATH =。 ./executable
b7713740(null)
另一种可能性是添加 RTLD_GLOBAL
当加载主库
:
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(./ sublibrary.so,RTLD_LAZY);
printf(%x%s,dlsym(handle,CreateClass),dlerror());
}
这样,你不需要链接任何东西 main-library.so
。
I have an issue when I try to use dlopen() to load a shared library into another shared library. I checked all tutorials on how to use dlopen() correctly. So here is the simplified code:
The main shared library contains a class with pure virtual functions which the sub-shared library (aka plug-in) must implement. Additionally, it has some other functions which are implemented with a default behavior. I created a macro which is added to every plug-in to have a symbol to load and create the class.
Main shared library
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; }
Build and link 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
The sub-shared library does only implement the pure-virtual functions. The other function can be overridden though it is optional.
Sub shared library
plugin-impl.cpp
Class B : public A {
public:
virtual int func1() { return 0; }
}
CREATE_CLASS(B)
These are the lines to build and link the sub-shared library.
Build and link 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
This is the line to open the sub-shared library. I tried LAZY, NOW, NOW | GLOBAL and so on, without any effects.
dlopen() call somewhere in the main-shared library:
handle = dlopen(file.c_str(), RTLD_LAZY);
Most of this is working very well. However, when I try to load the sub-shared library into the main shared library, dlopen complains about the undefined symbol of bool A::func2() const
. The function does only exists in the main shared library, so I guess it must be exported anyway. Please help me out! I am very confused!
SOLUTION
Because I cannot change the executable, I have to link the main-shared library with the sub-shared librarys by adding the following options to g++:
-L$(PLUGINDIR) -Wl,-R$(PLUGINDIR) -lmain-shared
With this set, it is not required to set the LD_LIBRARY_PATH
.
Since your sub-library needs symbols from the main library, I think it you want it to be linked with it. Try linking it like this:
g++ -g -O3 -Wall -Werror=overloaded-virtual -Wno-parentheses -fPIC -shared
-lmain-plugin subPlugin.o -o subPlugin.so
Probably you'll need to play with -L
as well.
This is what I tried:
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)
Another possibility is adding RTLD_GLOBAL
when loading 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());
}
That way, you needn't link anything with main-library.so
.
这篇关于C ++:使用dlopen()加载共享库时未定义的符号的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!