C ++:加载共享库使用dlopen时未定义的符号()(C++: Undefined symbols

2019-09-23 15:18发布

我有一个问题,当我尝试使用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

Answer 1:

由于从主库的分库需要的符号,我想它,你希望它与它联系在一起。 尝试将它链接是这样的:

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



文章来源: C++: Undefined symbols when loading shared library with dlopen()