2013-08-27 4 views
6

Warum bin ich die folgende Linker-Fehler bekommen, wenn mit libc Klirren ++ verwenden:Klirren ++ -stdlib = libC++ führt zu undefinierten Referenz

$ 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) 

Wo:

$ 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> >*) 

-Code ist einfach:

#include <poppler/PDFDoc.h> 

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

Antwort

7

Sie Fehler nach, sollte es wie Sie versuchen, eine libC++ mit stdlibc zu verbinden ++, die libC++ und stdlibC++ ist anders, stdlibC++ ist gcc C++ Standard-Bibliothek, wird es nicht miteinander kompatibel.

Für Ihr Problem, es ist wie Ihre libpoppler.so stdlibC++, verwendet aber Sie versuchen in der Befehlszeile call libC++ als Standard-lib, sie haben unterschiedliche Namen in der Verknüpfung Bühne, siehe Link am Ende von diese Antwort für das Detail warum. So

, vielleicht Ihre Lösung ändern Sie einfach den Kompilierungsbefehl zu

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

Bitte beachten Sie diese Frage ausführlich, warum std: __ 1 :: Satz und std :: set.

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

3

Weil libpoppler.so mit GNU stdlibC++ verknüpft ist. Alle Teile einer einzelnen ausführbaren Datei müssen mit demselben Standard-C und denselben Standard-C++ - Bibliotheken verknüpft sein.

Die einfachste Option ist, einfach mit der Standard-Standardbibliothek zu gehen. Beide sind jetzt meist C++ 11-komplett.

Alternativ können Sie eine Version von libpoppler.so gegen libc++ erstellen, aber Sie müssten einen anderen Namen angeben, damit der dynamische Linker den richtigen findet.

Im Link-Fehler können Sie sehen, dass libpoppler.so-std::set und std::less usw. bezieht, sondern möchten, dass Ihre Objekte zu std::__1::set und std::__1::less usw. beziehen, da ist GNU stdlibC++ und Clang libC++ Ansatz anders Versionierung.

3

Da libC++ einen anderen Namespace aus der GNU C++ - Standardbibliothek verwendet. Dieser Linker-Fehler ist eine gute Sache, weil das Layout der beiden Bibliotheken Typen für einige Typen sicherlich anders sein wird.

Also was das bedeutet ist, dass Ihre 'poppler'-Bibliothek gegen die GNU C++ - Standardbibliothek gebaut wurde, die eine Gruppe von Namen hat - während der Compiler die Deklarationen in libC++ für die Funktionsaufrufe in der Übersetzung Ihres Programms verwendet hat. Daher sucht der Linker nach Symbolen in den Objekten (z. B. der Poppler-Bibliothek), die die libC++ - Benennung für std-Bibliotheksdeklarationen haben, findet sie jedoch nicht, da sie nicht mit demselben Namen ausgegeben wurden - sie existieren wahrscheinlich in der Poppler-Bibliothek mit den GNU-Namen.

Natürlich interessiert Sie wahrscheinlich nur, wie dies behoben werden kann: Erstellen Sie sowohl Ihr Programm und die Poppler-Bibliothek mit der gleichen Standard-Bibliothek. Wenn Sie die Poppler-Bibliothek nicht erstellen können, müssen Sie darauf warten, dass sie eine Binärdatei ausgeben, die gegen libC++ erstellt wurde.