C ++:使用dlopen()加载共享库时未定义的符号 [英] C++: Undefined symbols when loading shared library with dlopen()

查看:262
本文介绍了C ++:使用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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆