我正在尝试使用Linux上的gcc 4.6构建一个共享库,它是动态加载的。正如Web上的许多文章以及之前的问题所述,我在库中提供了c风格的工厂方法来创建和销毁对象。代码 - 以最小的形式 - 看起来像这样:
base.h:
class base {
public:
base();
virtual ~base();
virtual int value() = 0;
};
base.cpp:
#include "base.h"
base::base() {}
base::~base() {}
main.cpp中:
#include "base.h"
#include <dlfcn.h>
#include <iostream>
int main() {
void* handle = dlopen("liblib.so", RTLD_NOW);
if(handle == NULL) std::cout << dlerror() << std::endl;
// dlsym, ...
}
lib.cpp:
class derived : public base {
public:
derived() {}
virtual ~derived() {}
virtual int value() { return 42; }
};
extern "C" derived* create_object() {
return new derived();
}
编译好:
g++ -shared -fPIC lib.cpp -o liblib.so
g++ base.cpp main.cpp -ldl -o app
在运行时,由于缺少typeinfo符号
,它会崩溃liblib.so: undefined symbol: _ZTI4base
在我之前发现的问题中,这个错误通常是由于某些错误“= 0;”或缺少虚拟功能的定义。但是在上面的例子中,base :: value是纯虚拟的,析构函数有一个定义。奇怪的是,nm报告_ZTI4base在app中定义:
$ nm app | grep _ZTI4base
0000000000601050 V _ZTI4base
那么为什么链接器不使用这个定义?
到目前为止,我发现使代码工作的唯一方法是在头文件中实现constructur和析构函数。然而,在执行此操作之后,base的相应符号在liblib.so中被nm报告并完全从app中消失,这可能意味着他们的定义被编译到库而不是app中,这不是我想要实现的。有没有人知道如何在不这样做的情况下完成上述工作?