2016-12-21 47 views
0

我用g++編譯了一個庫,我想用gcc來鏈接它。
問題是當鏈接反對我得到一個錯誤:如何刪除共享庫中符號周圍的字符?

未定義的引用「functionName`

(functionName是在庫中的函數名)

雖然功能存在於符號列表中,並在鏈接時指定gcc的路徑。

這是因爲該功能顯示在列表中與周圍的字符(我認爲這是壓倒一切?):

Z12functionNameiSt9__va_list

我知道要刪除這些字符我應該圍繞與extern "C"函數的聲明。我這樣做:

//header.hpp 
extern "C" int functionName(int argc, ...); 

但是周圍的字符仍然出現在符號列表中的函數名稱周圍。這就是爲什麼gcc找不到它。

我爲Linux手臂yokto交叉編譯與arm-poky-linux-gnueabi-gccarm-poky-linux-gnueabi-g++ Ubuntu桌面16

上爲什麼沒有被刪除周圍人物,我怎麼能刪除?我永遠不會重寫這個函數,所以如果這些都是重寫的話,我不需要它們。


編輯:

解決。其聲明中的函數簽名與其定義中的簽名不同......因此,關鍵字extern毫無用處。

int functionName(int argc, ...); //declaration 
int functionName(int argc, va_list args) //definition 
+0

也許你忘了'#include ' –

+0

@BasileStarynkevitch - 它包含 –

回答

1

這些字符是名稱混搭。它們對函數簽名進行編碼,以便C++重載可以正常工作(例如,int foo(int)int foo(float)是不同的符號)。

如果您的API是C,您需要修復庫以避免損壞。將其構建爲C或在其代碼中添加extern "C"。如果您的API旨在成爲C++,請從頭中刪除extern "C"

如果mangled名稱不匹配(不同的mangling),那麼你可能有一個ABI兼容性問題。在那種情況下,試圖解決鏈接問題是錯誤的解決方案。您需要確保使用與庫相同的ABI構建代碼。

c++filt工具應該能夠將損壞的符號解碼爲簽名。這對了解它們的區別很有用。

給你建庫與g++,正在和gcc鏈接,很可能你想有一個C API和重建與地方extern "C"圖書館是你所需要的。

+0

API是c(沒有類),但函數使用C++庫。我在頭文件中添加了'extern「C」''但是它並沒有刪除周圍的字符。可能是因爲函數簽名有一個省略號('...')? –

+0

@AlaaM。不,它可以很好地處理省略號。你是否用'extern「C」'重建了圖書館?我從你的文章中瞭解到,鏈接器查找'functionName',但庫包含'Z12functionNameiSt9__va_list',這意味着問題出現在庫中。還要確保庫實際上包含頭文件,而不是簡單地定義沒有任何'extern「C」'的函數。 – Olivier

+0

正如我在帖子中所說的,我知道問題出在圖書館。問題是它仍然包含周圍的字符 –

0

「周圍的字符」實際上是name mangling。所以最好說重名

你或許應該加上

#ifdef __cplusplus 
extern "C" { 
#endif 

你的(公共)頭文件的開頭附近(你會在C和C++的公共子集更好的代碼),並匹配

#ifdef __cplusplus 
}; // end of extern "C" 
#endif 

臨近結束。另見this

你應該用這些東西(不僅僅是單獨的函數)包裝所有的公共頭文件(也可能包含標準的C頭文件)。

您可以編譯gcc -H列出包含的標題或g++ -C -E獲取預處理的表單(並檢查它)。

+0

我不明白我剛纔提到的那些不同之處是怎麼樣的?我已經添加了'extern「C''。 –