Ich weiß das.
Aufruf der C-Funktion aus C ++:
Wenn meine Anwendung in C ++ wäre und ich Funktionen aus einer in C geschriebenen Bibliothek aufrufen müsste, hätte ich verwendet
//main.cpp
extern "C" void C_library_function(int x, int y);//prototype
C_library_function(2,4);// directly using it.
Dies würde den Namen nicht entstellen C_library_function
und der Linker würde den gleichen Namen in seinen * .lib-Eingabedateien finden und das Problem ist gelöst.
Aufruf der C ++ - Funktion von C ???
Aber hier erweitere ich eine große Anwendung, die in C geschrieben ist, und ich muss eine Bibliothek verwenden, die in C ++ geschrieben ist. Das Mangeln von Namen in C ++ verursacht hier Probleme. Linker beschwert sich über die ungelösten Symbole. Nun, ich kann den C ++ - Compiler nicht für mein C-Projekt verwenden, da das viele andere Dinge kaputt macht. Was ist der Ausweg?
Ich benutze übrigens MSVC
quelle
Antworten:
Sie müssen eine C-API erstellen, um die Funktionalität Ihres C ++ - Codes verfügbar zu machen. Grundsätzlich müssen Sie C ++ - Code schreiben, der als extern "C" deklariert ist und über eine reine C-API verfügt (z. B. ohne Klassen), die die C ++ - Bibliothek umschließt. Anschließend verwenden Sie die von Ihnen erstellte reine C-Wrapper-Bibliothek.
Ihre C-API kann optional einem objektorientierten Stil folgen, obwohl C nicht objektorientiert ist. Ex:
quelle
*.cpp file
ich auch die Funktionen in#ifdef _cplusplus
+ einschließenextern "C"
, um "undefinierte Verweise auf" Fehler zur Verbindungszeit zu vermeiden.Ich würde es folgendermaßen machen:
(Wenn Sie mit MSVC arbeiten, ignorieren Sie die GCC-Kompilierungsbefehle.)
Angenommen, ich habe eine C ++ - Klasse namens AAA , die in den Dateien aaa.h, aaa.cpp definiert ist , und die Klasse AAA hat eine Methode namens sayHi (const char * name) , die ich für C-Code aktivieren möchte.
Den C ++ - Code der Klasse AAA - Pure C ++ ändere ich nicht:
aaa.h
aaa.cpp
Kompilieren dieser Klasse wie regelmäßig für C ++ durchgeführt. Dieser Code "weiß nicht", dass er von C-Code verwendet wird. Verwenden des Befehls:
Jetzt auch in C ++ einen C-Connector erstellen. Definieren in den Dateien aaa_c_connector.h, aaa_c_connector.cpp . Dieser Connector definiert eine C-Funktion namens AAA_sayHi (cosnt char * name) , die eine Instanz von AAA verwendet und deren Methode aufruft :
aaa_c_connector.h
aaa_c_connector.cpp
Kompilieren Sie es erneut mit einem regulären C ++ - Kompilierungsbefehl:
Jetzt habe ich eine gemeinsam genutzte Bibliothek (libaaa_c_connector.so), die die C-Funktion AAA_sayHi (const char * name) implementiert . Ich kann jetzt eine C-Hauptdatei erstellen und alles zusammen kompilieren:
main.c
Kompilieren mit einem C-Kompilierungsbefehl:
Ich muss LD_LIBRARY_PATH so einstellen, dass es $ PWD enthält, und wenn ich die ausführbare Datei ./c_aaa ausführe, erhalte ich die erwartete Ausgabe:
BEARBEITEN:
Unter einigen Linux-Distributionen
-laaa
und-lstdc++
möglicherweise auch für den letzten Kompilierungsbefehl erforderlich. Danke an @AlaaM. für die Aufmerksamkeitquelle
gcc usecpp.c -L. -laaa_c_connector -Wl,-rpath,. -o c_aaa
usecpp.c
?gcc main.c -L. -laaa_c_connector -laaa -lstdc++ -o c_aaa
. Beachten Sie die-laaa
und-lstdc+++
main.c
zuusecpp.c
. Ich habe es gerade zurückgesetzt ... Über den anderen Kommentar sollte es auch so funktionieren wie es ist. Die zweite Zusammenstellung verwendet-laaa
und es sollte wahrscheinlich genug sein (ich habe es vor mehr als 1,5 Jahren geschrieben, ich erinnere mich nicht sehr gut, was ich getan habe, aber ich glaube, ich habe jede Zeile vor dem Posten getestet)Sie müssen einen Wrapper für C in C ++ schreiben, wenn Sie dies tun möchten. C ++ ist abwärtskompatibel, aber C ist nicht vorwärtskompatibel.
quelle
Angenommen, die C ++ - API ist C-kompatibel (keine Klassen, Vorlagen usw.), können Sie sie
extern "C" { ... }
genau wie beim Umkehren einbinden.Wenn Sie Objekte und andere niedliche C ++ - Inhalte verfügbar machen möchten, müssen Sie eine Wrapper-API schreiben.
quelle
Exportieren Sie Ihre C ++ - Funktionen als externes "C" (auch bekannt als C-Symbole) oder verwenden Sie das .def-Dateiformat, um nicht dekorierte Exportsymbole für den C ++ - Linker zu definieren, wenn er die C ++ - Bibliothek erstellt. Dann sollte der C-Linker keine Probleme beim Lesen haben
quelle
quelle
Sie können der Funktionsdeklaration das externe Schlüsselwort "C" voranstellen, z
extern "C" int Mycppfunction ()
{
// Code geht hier
return 0;
}}
Weitere Beispiele finden Sie bei Google nach dem Schlüsselwort "extern". Sie müssen noch einige Dinge tun, aber es ist nicht schwierig, viele Beispiele von Google zu erhalten.
quelle