与dlopen/dlsym一起使用时,dynamic_cast失败

Kee*_*Jan 13 c++ linux dynamic-cast dlopen dlsym

介绍

让我为这个长期问题道歉.它尽可能短,但不幸的是,它不是很短.

建立

我定义了两个接口,A和B:

class A // An interface
{
public:
  virtual ~A() {}

  virtual void whatever_A()=0;
};

class B // Another interface
{
public:
  virtual ~B() {}

  virtual void whatever_B()=0;
};
Run Code Online (Sandbox Code Playgroud)

然后,我有一个共享库"testc"构建类C的对象,同时实现A和B,然后传递指向它们的A接口的指针:

class C: public A, public B
{
public:
  C();
  ~C();

  virtual void whatever_A();
  virtual void whatever_B();
};

A* create()
{
  return new C();
}
Run Code Online (Sandbox Code Playgroud)

最后,我有一个第二个共享库"testd",它接受一个A*输入,并尝试将其转换为a B*,使用dynamic_cast

void process(A* a)
{
  B* b = dynamic_cast<B*>(a);
  if(b)
    b->whatever_B();
  else
    printf("Failed!\n");
}
Run Code Online (Sandbox Code Playgroud)

最后,我有主要的应用程序,A*在库之间传递:

A* a = create();
process(a);
Run Code Online (Sandbox Code Playgroud)

如果我构建我的主应用程序,链接到'testc'和'testd'库,一切都按预期工作.但是,如果我修改主应用程序以不链接'testc'和'testd',而是使用dlopen/ 在运行时加载它们dlsym,则dynamic_cast失败.

我不懂为什么.有线索吗?

附加信息

  • 用gcc 4.4.1,libc6 2.10.1(Ubuntu 9.10)测试
  • 示例代码可用

Kee*_*Jan 15

我在这里找到了我的问题的答案.据我了解,我需要让'testc'中的typeinfo可用于库'testd'.要在使用时执行此操作dlopen(),需要执行以下两项操作:

  • 链接库时,传递链接器-E选项,以确保它将所有符号导出到可执行文件,而不仅仅是那些未解析的符号(因为没有)
  • 使用时加载库dlopen(),添加RTLD_GLOBAL选项,以确保导出的符号testc也可用testd


bma*_*ies 5

通常,gcc不支持跨dlopen边界的RTTI.我有这个搞乱的尝试/捕获的个人经验,但你的问题看起来更像是相同的.可悲的是,我担心你需要在dlopen上坚持简单的东西.