2012-07-30 53 views
6

我想在Linux上動態加載使用gcc 4.6來構建共享庫。正如網絡上的許多文章以及以前的問題所述,我在庫中提供了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, ... 
} 

庫。 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 

在運行時,但它崩潰,因爲缺少所屬類別符號

liblib.so: undefined symbol: _ZTI4base 

在我這裏找到了前面的問題,這種錯誤通常是由於無論是一些失蹤「= 0;」或虛擬功能的缺失定義。然而在上面的例子中,base :: value是純虛擬的,析構函數有一個定義。奇怪的是納米報告_ZTI4base如definied在app:

$ nm app | grep _ZTI4base 
0000000000601050 V _ZTI4base 

那麼,爲什麼不使用連接器這樣的定義?

我發現到目前爲止獲得代碼工作的唯一方法是在頭文件中實現構造器和析構器。然而,這樣做後,base的相應符號會以nm的形式報告liblib.so,並且完全從應用程序中消失,這可能意味着它們的定義被編譯到庫中而不是應用程序中,這不是我想要實現的。有沒有人有一個想法如何在不這樣做的情況下獲得上述工作?

+1

將'--demangle'設置爲'nm'來查看函數的demangled名稱。 – Shahbaz 2012-07-30 22:21:19

回答

2

鏈接程序時需要-rdynamic選項,以導出其符號並使其可用於裝載有dlopen()的庫。

相關問題