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.c

    Wie 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_welt

    kompilieren 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 42

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


  • Mod

    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?


  • Mod

    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.


  • Mod

    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.


Anmelden zum Antworten