Ich habe eine C-Funktion, die ich aus C ++ aufrufen möchte. Ich konnte keinen extern "C" void foo()
Ansatz verwenden, da die C-Funktion nicht mit g ++ kompiliert werden konnte. Aber es kompiliert gut mit gcc. Irgendwelche Ideen, wie man die Funktion aus C ++ aufruft?
87
g++
Fehlermeldungen schreibenvoid valid_in_C_but_not_in_CPlusPlus(size_t size) { char variable_length_array[size]; }
void f(void *pv) { int *pi = pv; *pi = 42; }
^^Antworten:
Kompilieren Sie den C-Code wie folgt:
Dann lautet der C ++ - Code wie folgt:
Verknüpfen Sie sie dann mit dem C ++ - Linker:
Sie müssen dem C ++ - Compiler auch mitteilen, dass ein C-Header kommt, wenn Sie die Deklaration für die C-Funktion einfügen. Also
othercode.cpp
beginnt mit:somecode.h
sollte etwas enthalten wie:(In diesem Beispiel habe ich gcc verwendet, aber das Prinzip ist für jeden Compiler dasselbe. Erstellen Sie es separat als C bzw. C ++ und verknüpfen Sie es dann miteinander.)
quelle
extern "C"
in den Header einschließen#ifdef __cplusplus
.Lassen Sie mich die Teile der anderen Antworten und Kommentare zusammenfassen, um Ihnen ein Beispiel mit sauber getrenntem C- und C ++ - Code zu geben:
Der C-Teil:
foo.h :
foo.c
Kompilieren Sie dies mit
gcc -c -o foo.o foo.c
.Der C ++ - Teil:
bar.cpp
Kompilieren Sie dies mit
g++ -c -o bar.o bar.cpp
Und dann alles miteinander verbinden:
Begründung: Der C-Code sollte ein einfacher C-Code sein, Nr
#ifdef
s für "Vielleicht rufe ich das eines Tages aus einer anderen Sprache auf". Wenn einige C ++ Programmierer Ihre C - Funktionen aufruft, es ist ihr Problem , wie das zu tun, nicht verkaufen. Und wenn Sie der C ++ - Programmierer sind, gehört der C-Header möglicherweise nicht Ihnen und Sie sollten ihn nicht ändern, sodass die Behandlung nicht entwirrter Funktionsnamen (dh derextern "C"
) in Ihren C ++ - Code gehört.Sie können sich natürlich auch einen praktischen C ++ - Header schreiben, der nichts anderes tut, als den C-Header in eine
extern "C"
Deklaration zu verpacken .quelle
Ich stimme der Antwort von Prof. Falken zu , aber nach dem Kommentar von Arne Mertz möchte ich ein vollständiges Beispiel geben (der wichtigste Teil ist der
#ifdef __cplusplus
):somecode.h
somecode.c
othercode.hpp
othercode.cpp
Dann folgen Sie den Anweisungen von Prof. Falken zum Kompilieren und Verknüpfen.
Dies funktioniert , weil , wenn Sie mit dem Kompilieren
gcc
, das Makro__cplusplus
nicht definiert ist , so dass der Headersomecode.h
enthalten insomecode.c
wie dies nach der Vorverarbeitung:und wenn Sie mit dem Kompilieren
g++
, dann__cplusplus
wird definiert, und so den Header enthalten inothercode.cpp
ist nun wie folgt aus:quelle
#ifdef __cplusplus
in C-Code nicht. Der C-Code ist die untere Ebene und sollte sich nicht darum kümmern müssen, ob er eines Tages aus dem C ++ - Code aufgerufen wird. Imo,#ifdef
das nur in C ++ - Code verwendet wird, wenn Sie einen C-Bindungsheader für eine in C ++ geschriebene Bibliothek bereitstellen möchten, nicht umgekehrt.Diese Antwort ist inspiriert von einem Fall, in dem Arnes Begründung richtig war. Ein Anbieter hat eine Bibliothek geschrieben, die einst sowohl C als auch C ++ unterstützte. Die neueste Version unterstützte jedoch nur C. Die folgenden im Code verbliebenen Anweisungen waren irreführend:
Der Versuch, in C ++ zu kompilieren, hat mich mehrere Stunden gekostet. Das einfache Aufrufen von C aus C ++ war viel einfacher.
Die ifdef __cplusplus-Konvention verstößt gegen das Prinzip der Einzelverantwortung. Ein Code, der diese Konvention verwendet, versucht zwei Dinge gleichzeitig zu tun:
Es ist, als würde man versuchen, gleichzeitig in amerikanischem und britischem Englisch zu schreiben. Dies wirft unnötigerweise einen #ifdef __thequeensenglish Schraubenschlüssel #elif __yankeeenglish Schraubenschlüssel #else ein nutzloses Werkzeug, das es schwieriger macht, den Code #endif in den Code einzulesen.
Für einfachen Code und kleine Bibliotheken funktioniert möglicherweise die Konvention ifdef __cplusplus. Für komplexe Bibliotheken ist es jedoch am besten, die eine oder andere Sprache auszuwählen und dabei zu bleiben. Die Unterstützung einer der Sprachen erfordert weniger Wartung als der Versuch, beide zu unterstützen.
Dies ist eine Aufzeichnung der Änderungen, die ich an Arnes Code vorgenommen habe, damit er unter Ubuntu Linux kompiliert werden kann.
foo.h :
foo.c
bar.cpp
Makefile
quelle