2009-01-26 59 views
18

我正在編寫一些使用動態共享庫作爲插件的代碼。使用dlopen加載庫時收到「未定義符號」錯誤

我對共享庫的構建命令行的樣子:

cc -shared -fPIC -o module.so -g -Wall module.c 

在模塊內,我可以調用在已加載的主執行程序中的任何其他共享庫函數。

但是我無法訪問(導出)可執行文件本身的函數(我得到了undefined symbol錯誤)。

我對dlopen調用如下:

void *handle = dlopen(plugin, RTLD_NOW); 

任何人都可以請告知我模塊如何調用回我的可執行文件,而不必把所有的可執行文件的實用功能到另一個共享庫?

回答

5

我自己找到了答案。

我不得不將--export-dynamic標誌添加到主可執行文件的鏈接選項。

當創建一個動態鏈接的可執行 ,所有符號添加到 動態符號表。動態 符號表是在運行時從動態對象 可見的符號集 。

如果不使用此選項, 動態符號表通常 只包含那些 通過在鏈接中提到的一些動態對象 引用符號。

如果使用「dlopen的」加載動態 對象,需要重提 由程序定義的符號, 而不是其他一些動態對象, 那麼你可能需要使用 此選項時鏈接程序 本身。

29

正確的解決方案是將-rdynamic添加到主可執行文件的鏈接命令。這將爲ld添加適當的選項(當使用GNU ld時,恰好是--export-dynamic)。

直接添加--export-dynamic在技術上是不正確的:它是一個鏈接器選項,因此應該添加爲-Wl,--export-dynamic-Wl,-E。這也比-rdynamic便攜便攜(其他連接器有一個等效,但選擇本身是不同的)。

+0

此解決方案也適用於使用Boost擴展時,因爲shared_library類正在使用dlopen(在Linux上)加載庫。 – 2013-01-03 07:04:00

4

當我遇到同樣的問題時,我只使用了以下解決方案。在加載任何插件之前,只需加載程序本身,將其符號帶入動態表格:

dlopen(NULL,RTLD_NOW|RTLD_GLOBAL); 

我認爲解決方案更好。原因是,它也解決了同樣的問題,如果你的程序(或三方模塊)與共享庫鏈接(而不是在運行時),哪些符號需要在動態表中鏈接(而不是在運行時);

b)不能使用-rdynamic標誌重新編譯該模塊。

相關問題