一尘不染

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

linux

介绍

让我为这个长期的问题表示歉意。它要尽我所能,但是很不幸,它不是很短。

设定

我定义了两个接口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;
};

然后,我有一个共享库“ 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();
}

最后,我有一个第二共享库“TESTD”,需要一个A*作为输入,并尝试将其转换为一个B*,使用dynamic_cast

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

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

A* a = create();
process(a);

如果我构建主应用程序,并链接到“ testc”和“
testd”库,那么一切都会按预期进行。但是,如果我修改主应用程序以不链接到’testc’和’testd’,而是使用dlopen/
在运行时加载它们dlsym,则dynamic_cast失败。

我不明白为什么。有什么线索吗?

附加信息

  • 使用gcc 4.4.1,libc6 2.10.1(Ubuntu 9.10)进行了测试
  • 可用的示例代码

阅读 288

收藏
2020-06-03

共1个答案

一尘不染

我在这里找到了问题的答案。据我了解,我需要将’testc’中的typeinfo提供给’testd’库。要在使用时执行此操作dlopen(),还需要做两件事:

  • 链接库时,请向链接器传递-E选项,以确保将所有符号导出到可执行文件,而不只是导出未在其中解析的符号(因为没有)。
  • 使用加载库时dlopen(),请添加RTLD_GLOBAL选项,以确保导出的符号testc也可用于testd
2020-06-03