2012-07-30 18 views
6

私は、動的にロードされるLinuxでgcc 4.6を使用して共有ライブラリを構築しようとしています。 Web上の多くの記事やこれまでの質問に記載されているように、私はオブジェクトを作成して破壊するためにライブラリにCスタイルのファクトリメソッドを提供します。動的にロードされたライブラリで定義されていないシンボル "typeinfo"

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 

なぜこの定義を使用していないのですか?

私が今までにコードを動作させるために見つけた唯一の方法は、ヘッダファイルにconstructurとdestructorを実装することです。しかし、これに続いてbaseに対応するシンボルはnmlによってliblib.soに報告され、appから完全に消えてしまいます。これはおそらくその定義がライブラリにコンパイルされていてappにコンパイルされていないことを意味します。これをしなくても上記の作業をどうやって行うのか考えている人はいますか?

+1

'--demangle'を' nm'に指定すると、関数のデングランド名が表示されます。 – Shahbaz

答えて

2

プログラムをリンクするときにシンボルをエクスポートし、dlopen()がロードされたライブラリで使用できるようにするには、-rdynamicオプションが必要です。