C++ in C, wie richtig kompilieren/linken?
-
Hi,
ich möchte in meinem c Programm eine cpp-Funktion nutzen.
(hier ein alter thread dazu https://www.c-plusplus.net/forum/273372-full )Ich habe also:
-den C++ Code: cpp.cpp
-den Wrapper mit 'extern C': wrapper.cpp
-und mein eigentliches Programm in C: c.cWie im Thread beschrieben kann ich es mit:
g++ cpp.cpp -c -o cpp.o
g++ wrapper.cpp -c -o wrapper.o
gcc c.c -c -o c.o
g++ cpp.o wrapper.o c.o -o hallo_weltkompilieren und ausführen. Jedoch wird am Ende der C++ Kompiler verwendet.
Ich würde es aber gern mit dem C Kompiler haben.
Nachdem ich eine Weile gessucht/probiert habe, ging es damit:g++ -fPIC -c cpp.cpp
g++ -fPIC -c wrap.cpp
g++ -shared -o libcpp.so wrap.o cpp.o
gcc -L/home/user/path/ c.c -o hallo_welt -lcpp
export LD_LIBRARY_PATH=/home/user/path/:$LD_LIBRARY_PATH
./hallo_welt 42Die c.c wird mit der Zeit verändert werden und auch andere Personen werden etwas dran rumprobieren. Die Angabe der lib (-L und -lcpp) und der export kann da zu Problemen führen. Gibt es einen anderen einfacheren Weg? z.B ohne Bibliothek erstellen? (oder ohne fPIC)
-
Das am Ende ist kein Compileraufruf, sondern ein Linkeraufruf. Daher: Warum willst du das ändern¹? Der einzige Unterschied zwischen g++ und gcc ist in dem Fall, dass g++ die Pfade und Bibliotheken, die du da von Hand setzt, bereits standardmäßig korrekt voreingestellt hat.
PS: Laut Anleitung ist g++ äquivalent zu
gcc -xc++ -lstdc++ -shared-libgcc
Man sollte also meinen, dass es mit diesem Aufruf reibungslos funktionieren wird, wenn du g++ einfach damit ersetzt und sonst nichts änderst.
¹: Selbst wenn es ein Compileraufruf wäre, wäre mir rätselhaft, wieso du das ändern möchtest.
-
SeppJ schrieb:
Das am Ende ist kein Compileraufruf, sondern ein Linkeraufruf. Daher: Warum willst du das ändern¹? Der einzige Unterschied zwischen g++ und gcc ist in dem Fall, dass g++ die Pfade und Bibliotheken, die du da von Hand setzt, bereits standardmäßig korrekt voreingestellt hat.
Ja,das das stimmmt. Ich meinte damit den Befehl 'g++'. Bisher dachte ich, gcc ist nur für C aber damit kann man auch c++ kompilieren.
Was jeodch noch anders ist, dass ich die .o mit -fPIC kompillieren musste (für lib). Wie würde nun gcc ohne lib gehen?SeppJ schrieb:
PS: Laut Anleitung ist g++ äquivalent zu
gcc -xc++ -lstdc++ -shared-libgcc
Man sollte also meinen, dass es mit diesem Aufruf reibungslos funktionieren wird, wenn du g++ einfach damit ersetzt und sonst nichts änderst.
Also
g++ cpp.o wrapper.o c.o -o hallo_welt
wird zu:
gcc -xc++ -lstdc++ -shared-libgcc cpp.o wrap.o c.c -o hallo_welt
?
Das wirft dann sehr viele Fehler von dieser Sorte (10 auch andere Werte)):c.o:8:4: error: stray '\10' in program c.o:8:789: warning: null character(s) ignored
Das kompilieren und linken sollte auch noch zusammen sein:
Also mit g++ z.B.:g++ cpp.o wrapper.o c.c -o hallo_welt
(also c.c, statt c.o)
Dann kompiliert es die c.c doch in C++, oder?
-
Ihooq schrieb:
Also
g++ cpp.o wrapper.o c.o -o hallo_welt
wird zu:
gcc -xc++ -lstdc++ -shared-libgcc cpp.o wrap.o c.c -o hallo_welt
?
Das wirft dann sehr viele Fehler von dieser Sorte (10 auch andere Werte)):c.o:8:4: error: stray '\10' in program c.o:8:789: warning: null character(s) ignored
Wo kommt denn das c.c her? Jetzt hast du ein C-Programm im C++-Modus übersetzt, kein Wunder, dass das nicht funktioniert. Wobei diese speziellen Fehler aber eher komisch sind, das klingt eher nach einem echten Fehler in deinem Programm.
Das kompilieren und linken sollte auch noch zusammen sein:
Also mit g++ z.B.:g++ cpp.o wrapper.o c.c -o hallo_welt
(also c.c, statt c.o)
Dann kompiliert es die c.c doch in C++, oder?Ja. Soll das so sein? Vermutlich nicht.
PS: Ich habe es gerade extra noch einmal ausprobiert: g++ mit obigem Ausdruck zu ersetzen funktioniert hervorragend. Dein Fehler muss entweder ganz woanders liegen oder darin, dass du durcheinander kommst.
PPS: Du musst natürlich auf die richtige Reihenfolge beim Linken achten, die -lstdc++ wird in aller Regel hinter den Objektdateien stehen müssen.
PPPS: Ahh, ich hab's: Wenn das -xc++ vor den Objektdateien steht, dann versucht er die Objektdateien als C++ zu übersetzen, anstatt zu linken. Das geht natürlich schief und man erhält genau die Fehler, die du hast. Wenn man die Objektdateien vorne einreiht (wo sie sowieso stehen sollten, siehe PPS), dann ist er klug genug, das -xc++ zu ignorieren. Du kannst es natürlich auch ganz weglassen.
Also zusammengefasst:
g++ {args} = gcc {args} -xc++ -lstdc++ -shared-libgcc
-
Tut mir Leid, dass ich erst jetzt antworten kann. Ich war ganz vertieft in einen anderen Problem.
Ich habe es getestet und kann es damit sogar mit der .c machen.
Also:gcc cpp.o wrapper.o c.c -o test -xc++ -lstdc++ -shared-libgcc
Alles in einer Zeile :). Vielen Dank dafür.
gcc cpp.o wrap.o c.c -o test -lstdc++
geht übrigends auch schon (zumindest in meinem Fall).
die richtige Reihenfolge beim Linken achten,
Ja, das weiß ich immer nicht, wo was stehen muss. Oft gehen ja verschiedene Reihenfolgen.
Und wenn man im Inet sucht: z.B
https://www.oreilly.de/german/freebooks/rlinux3ger/ch132.html
Da stehen die Objekt-Dateien mal hinten und mal in der Mitte aber nicht, wie empfohlen vorne.Und in der manpage stehen haufen Parameter aber nicht was sie bedeuten.
Naja genug gelernt für heute.
Nochmal vielen Dank.
-
Linkerreihenfolge: Vorne stehen die Dinge, die von den Dingen weiter hinten abhängen sollen.
Ein bisschen Erklärung zu der Kommandozeile, da du anscheinend nicht in der Lage warst, diese selber zu erforschen:
xc++ ist ein Schalter für den Compiler, der die Sprache auf C++ stellt. Wenn du nur linkst, ist dieser natürlich egal. Wenn du C-Dateien damit übersetzt, werden diese als C++ übersetzt. Dies mag bei einfachen Hello World Programmen noch funktionieren, wird aber im Allgemeinen nicht so sein.
lstc++ ist ein Linkerschalter und sagt, dass die C++-Standardbibliothek dazu gelinkt werden soll. Wenn du nur compilierst, ist dieser natürlich egal. Du brauchst es natürlich nur dann zwingend, wenn dein C++-Code überhaupt Teile der C++-Bibliothek benutzt. Einfache Beispiele funktionieren eventuell auch ohne.
shared-libgcc ist ein Linkerschalter, der sagt, dass eine bestimmte Variante der C-Laufzeitbibliothek benutzt werden soll. Wenn du nur compilierst, ist dieser natürlich egal. Die shared-Variante ist in der Lage, korrekt mit Exceptions umzugehen. Das brauchst du natürlich nur dann, wenn dein C++-Code überhaupt Exceptions werfen kann. Dies wird in aller Regel der Fall sein, selbst wenn du dir dessen nicht bewusst bist. Einfache Beispiele funktionieren aber eventuell auch ohne.