2013-08-27 57 views
6

爲什麼我使用鐺時的libC++我得到以下鏈接錯誤:鐺++ -stdlib =的libC++導致未定義的參考

$ clang++ -stdlib=libc++ po.cxx -lpoppler 
/tmp/po-QqlXGY.o: In function `main': 
po.cxx:(.text+0x33): undefined reference to `Dict::lookup(char*, Object*, std::__1::set<int, std::__1::less<int>, std::__1::allocator<int> >*)' 
clang: error: linker command failed with exit code 1 (use -v to see invocation) 

其中:

$ nm -D /usr/lib/x86_64-linux-gnu/libpoppler.so | grep lookup | c++filt| grep \ Dict::lookup\(
00000000000c1870 T Dict::lookup(char*, Object*, std::set<int, std::less<int>, std::allocator<int> >*) 

代碼很簡單:

#include <poppler/PDFDoc.h> 

int main() 
{ 
    Dict *infoDict; 
    Object obj; 
    infoDict->lookup((char*)"key", &obj); 
    return 0; 
} 

回答

7

根據你的錯誤,它應該像你試圖鏈接一個libC++ stdlibC++, libC++和stdlibC++是不同的,stdlibC++是gcc的C++標準庫,它不會相互兼容。

對於你的問題,就像你的libpoppler.so使用的是stdlibC++, ,但是在你的clang命令行中,你嘗試使用libC++作爲標準lib,它們在鏈接階段有不同的名稱,請參見鏈接這個答案的細節爲什麼。

所以,也許您的解決方案只是改變編譯命令

clang++ -stdlib=libstdc++ po.cxx -lpoppler 

請參閱此問題詳細爲什麼STD:__ 1 ::集和std ::設置。

Why can't clang with libc++ in c++0x mode link this boost::program_options example?

3

因爲libpoppler.so與GNU stdlibC++鏈接。單個可執行文件的所有部分必須與相同的標準C和相同的標準C++庫進行鏈接。

最簡單的選擇是使用默認的標準庫。兩者現在大都是C++ 11-complete。

或者,您可以針對libc++構建libpoppler.so版本,但是您必須爲其指定不同的名稱,以便動態鏈接程序找到正確的名稱。

在鏈接錯誤,你可以看到libpoppler.sostd::setstd::less等,但你的對象要引用std::__1::setstd::__1::less等。這是因爲GNU stdlibC++和鏘的libC++版本的方法不同。

3

由於libC++使用GNU C++標準庫中的不同名稱空間。這個鏈接器錯誤是一件好事,因爲對於某些類型,這兩個庫類型的佈局肯定會有所不同。

那麼這意味着你的'poppler'庫是針對GNU C++標準庫構建的,它有一組名稱 - 而編譯器則使用libC++中的聲明來進行程序翻譯中的函數調用。因此,鏈接器在對象(例如poppler庫)中尋找符號,這些符號具有用於std庫聲明的libC++命名,但是它沒有找到它們,因爲它們沒有用相同的名稱發射 - 它們可能存在於poppler庫中與GNU的名字。

當然,您可能只是在意如何解決這個問題:使用相同的標準庫構建程序和poppler庫。如果你不能建立poppler庫,你將不得不等待它們推出一個針對libC++構建的二進制文件。