Linuxでgcc4.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をアプリで定義されていると報告します。
$ nm app | grep _ZTI4base
0000000000601050 V _ZTI4base
では、なぜリンカーはこの定義を使用しないのでしょうか。
コードを機能させるためにこれまでに見つけた唯一の方法は、ヘッダーファイルにコンストラクタとデストラクタを実装することです。ただし、これを行った後、baseの対応するシンボルはliblib.soでnmによって報告され、アプリから完全に消えます。これは、おそらく、それらの定義がアプリではなくライブラリにコンパイルされたことを意味します。これは、私が達成したかったことではありません。これを行わずに上記を機能させる方法を誰かが考えていますか?