C und C ++ sind oberflächlich ähnlich, aber jeder kompiliert sich zu einem ganz anderen Satz von Code. Wenn Sie eine Header-Datei in einen C ++ - Compiler einfügen, erwartet der Compiler C ++ - Code. Wenn es sich jedoch um einen C-Header handelt, erwartet der Compiler, dass die in der Header-Datei enthaltenen Daten in ein bestimmtes Format kompiliert werden - das C ++ - 'ABI' oder 'Application Binary Interface', sodass der Linker erstickt. Dies ist der Übergabe von C ++ - Daten an eine Funktion vorzuziehen, die C-Daten erwartet.
(Um wirklich auf den Punkt zu kommen, "entstellt" C ++ 's ABI im Allgemeinen die Namen ihrer Funktionen / Methoden. Wenn Sie also aufrufen, printf()ohne den Prototyp als C-Funktion zu kennzeichnen, generiert C ++ tatsächlich Code-Aufrufe _Zprintfund zusätzlichen Mist am Ende. )
Also: Verwenden Sie diese extern "C" {...}Option, wenn Sie einen AC-Header einschließen - so einfach ist das. Andernfalls wird der kompilierte Code nicht übereinstimmen, und der Linker wird ersticken. Für die meisten Header benötigen Sie jedoch nicht einmal die, externda die meisten System-C-Header bereits die Tatsache berücksichtigen, dass sie möglicherweise im C ++ - Code und bereits in externihrem Code enthalten sind.
Könnten Sie bitte näher darauf eingehen, dass "die meisten System-C-Header bereits die Tatsache berücksichtigen, dass sie möglicherweise im C ++ - Code enthalten sind und ihren Code bereits extern enthalten". ?
Bulat M.
7
@BulatM. Sie enthalten ungefähr Folgendes: #ifdef __cplusplus extern "C" { #endif Wenn sie aus einer C ++ - Datei aufgenommen werden, werden sie weiterhin als C-Header behandelt.
Calmarius
111
extern "C" legt fest, wie Symbole in der generierten Objektdatei benannt werden sollen. Wenn eine Funktion ohne externes "C" deklariert wird, verwendet der Symbolname in der Objektdatei die C ++ - Namensverknüpfung. Hier ist ein Beispiel.
Gegeben test.C wie folgt:
void foo(){}
Das Kompilieren und Auflisten von Symbolen in der Objektdatei ergibt:
$ g++-c test.C
$ nm test.o0000000000000000 T _Z3foov
U __gxx_personality_v0
Die foo-Funktion heißt eigentlich "_Z3foov". Diese Zeichenfolge enthält unter anderem Typinformationen für den Rückgabetyp und die Parameter. Wenn Sie stattdessen test.C wie folgt schreiben:
extern"C"{void foo(){}}
Dann kompilieren und betrachten Sie Symbole:
$ g++-c test.C
$ nm test.o
U __gxx_personality_v0
0000000000000000 T foo
Sie erhalten eine C-Verknüpfung. Der Name der "foo" -Funktion in der Objektdatei ist nur "foo" und enthält nicht alle ausgefallenen Typinformationen, die aus der Namensverfälschung stammen.
Sie fügen in der Regel einen Header in extern "C" {} ein, wenn der dazugehörige Code mit einem C-Compiler kompiliert wurde, Sie ihn jedoch aus C ++ aufrufen möchten. Wenn Sie dies tun, teilen Sie dem Compiler mit, dass alle Deklarationen im Header die C-Verknüpfung verwenden. Wenn Sie Ihren Code verknüpfen, enthalten Ihre .o-Dateien Verweise auf "foo", nicht auf "_Z3fooblah", was hoffentlich mit dem übereinstimmt, mit dem Sie in der Bibliothek verknüpfen.
Die meisten modernen Bibliotheken werden solche Header schützen, sodass Symbole mit der richtigen Verknüpfung deklariert werden. zB in vielen Standard-Headern finden Sie:
Dadurch wird sichergestellt, dass die Symbole in Ihrer Objektdatei mit denen in der C-Bibliothek übereinstimmen, wenn C ++ - Code den Header enthält. Sie sollten nur externes "C" {} um Ihren C-Header setzen müssen, wenn dieser alt ist und diese Wachen noch nicht hat.
In C ++ können Sie verschiedene Entitäten haben, die einen Namen gemeinsam haben. Zum Beispiel ist hier eine Liste von Funktionen, die alle foo heißen :
A::foo()
B::foo()
C::foo(int)
C::foo(std::string)
Um zwischen allen zu unterscheiden, erstellt der C ++ - Compiler in einem Prozess, der als Namensverknüpfung oder -dekoration bezeichnet wird, eindeutige Namen für jeden Namen. C-Compiler tun dies nicht. Darüber hinaus kann jeder C ++ - Compiler dies auf andere Weise tun.
extern "C" weist den C ++ - Compiler an, keine Namensänderung für den Code in geschweiften Klammern vorzunehmen. Auf diese Weise können Sie C-Funktionen in C ++ aufrufen.
Dies hängt mit der Art und Weise zusammen, wie die verschiedenen Compiler das Namens-Mangling durchführen. Ein C ++ - Compiler entstellt den Namen eines aus der Header-Datei exportierten Symbols auf völlig andere Weise als ein C-Compiler. Wenn Sie also versuchen, eine Verknüpfung herzustellen, wird ein Linkerfehler angezeigt, der besagt, dass Symbole fehlen.
Um dies zu beheben, weisen wir den C ++ - Compiler an, im "C" -Modus ausgeführt zu werden, damit die Namensverwaltung auf die gleiche Weise wie beim C-Compiler ausgeführt wird. Danach werden die Linkerfehler behoben.
C und C ++ haben unterschiedliche Regeln für Symbolnamen. Mit Symbolen weiß der Linker, dass der Aufruf der Funktion "openBankAccount" in einer vom Compiler erstellten Objektdatei eine Referenz auf die Funktion ist, die Sie "openBankAccount" in einer anderen Objektdatei genannt haben, die von derselben (oder kompatiblen) aus einer anderen Quelldatei erstellt wurde. Compiler. Auf diese Weise können Sie ein Programm aus mehr als einer Quelldatei erstellen. Dies ist eine Erleichterung bei der Arbeit an einem großen Projekt.
In C ist die Regel sehr einfach, Symbole befinden sich sowieso alle in einem einzigen Namensraum. Die Ganzzahl "socks" wird also als "socks" und die Funktion count_socks als "count_socks" gespeichert.
Mit dieser einfachen Symbolbenennungsregel wurden Linker für C und andere Sprachen wie C erstellt. Symbole im Linker sind also nur einfache Zeichenfolgen.
In C ++ können Sie in der Sprache Namespaces, Polymorphismus und verschiedene andere Dinge verwenden, die mit einer so einfachen Regel in Konflikt stehen. Alle sechs polymorphen Funktionen mit der Bezeichnung "Hinzufügen" müssen unterschiedliche Symbole haben. Andernfalls wird das falsche von anderen Objektdateien verwendet. Dies geschieht durch "Zerfleischen" (das ist ein technischer Begriff) der Namen von Symbolen.
Wenn Sie C ++ - Code mit C-Bibliotheken oder Code verknüpfen, benötigen Sie externes "C" für alles, was in C geschrieben ist, z. B. Header-Dateien für die C-Bibliotheken, um Ihrem C ++ - Compiler mitzuteilen, dass diese Symbolnamen nicht entstellt werden dürfen, während der Rest von Ihr C ++ - Code muss natürlich entstellt sein, sonst funktioniert es nicht.
Wenn Sie C-Bibliotheken mit C ++ - Objektdateien verknüpfen
Was passiert auf Compiler- / Linker-Ebene, für das wir es verwenden müssen?
C und C ++ verwenden unterschiedliche Schemata für die Symbolbenennung. Dies weist den Linker an, das C-Schema zu verwenden, wenn er in der angegebenen Bibliothek verknüpft.
Wie löst dies in Bezug auf das Zusammenstellen / Verknüpfen die Probleme, die es erforderlich machen, es zu verwenden?
Mit dem C-Namensschema können Sie auf Symbole im C-Stil verweisen. Andernfalls würde der Linker Symbole im C ++ - Stil ausprobieren, die nicht funktionieren würden.
Sie sollten extern "C" immer dann verwenden, wenn Sie einen Header einfügen, der Funktionen definiert, die sich in einer Datei befinden, die von einem C-Compiler kompiliert und in einer C ++ - Datei verwendet wird. (Viele Standard-C-Bibliotheken enthalten diese Prüfung möglicherweise in ihren Headern, um sie für den Entwickler einfacher zu machen.)
Wenn Sie beispielsweise ein Projekt mit 3 Dateien, util.c, util.h und main.cpp, haben und sowohl die .c- als auch die .cpp-Dateien mit dem C ++ - Compiler (g ++, cc usw.) kompiliert werden, ist dies nicht der Fall. Es wird nicht wirklich benötigt und kann sogar Linkerfehler verursachen. Wenn Ihr Erstellungsprozess einen regulären C-Compiler für util.c verwendet, müssen Sie externes "C" verwenden, wenn Sie util.h einschließen.
Was passiert ist, dass C ++ die Parameter der Funktion in ihrem Namen codiert. So funktioniert Funktionsüberladung. Alles, was einer C-Funktion passieren kann, ist das Hinzufügen eines Unterstrichs ("_") am Anfang des Namens. Ohne externes "C" sucht der Linker nach einer Funktion namens DoSomething @@ int @ float (), wenn der tatsächliche Name der Funktion _DoSomething () oder nur DoSomething () lautet.
Die Verwendung von externem "C" löst das obige Problem, indem dem C ++ - Compiler mitgeteilt wird, dass er nach einer Funktion suchen soll, die der C-Namenskonvention anstelle der C ++ - folgt.
Der C ++ - Compiler erstellt Symbolnamen anders als der C-Compiler. Wenn Sie also versuchen, eine Funktion aufzurufen, die sich in einer C-Datei befindet, die als C-Code kompiliert wurde, müssen Sie dem C ++ - Compiler mitteilen, dass die Symbolnamen, die aufgelöst werden sollen, anders aussehen als standardmäßig. Andernfalls schlägt der Verknüpfungsschritt fehl.
Das extern "C" {}Konstrukt weist den Compiler an, die in geschweiften Klammern deklarierten Namen nicht zu entstellen. Normalerweise "erweitert" der C ++ - Compiler die Funktionsnamen so, dass sie Typinformationen über Argumente und den Rückgabewert codieren. Dies nennt man den verstümmelten Namen . Das extern "C"Konstrukt verhindert das Zerfleischen.
Es wird normalerweise verwendet, wenn C ++ - Code eine C-Sprachbibliothek aufrufen muss. Es kann auch verwendet werden, wenn eine C ++ - Funktion (z. B. aus einer DLL) C-Clients zur Verfügung gestellt wird.
Dies wird verwendet, um Probleme mit der Namensveränderung zu beheben. extern C bedeutet, dass sich die Funktionen in einer "flachen" API im C-Stil befinden.
Dekompilieren Sie eine g++generierte Binärdatei, um zu sehen, was los ist
Um zu verstehen, warum dies externerforderlich ist, müssen Sie am besten anhand eines Beispiels verstehen, was in den Objektdateien im Detail vor sich geht:
main.cpp
void f(){}void g();extern"C"{void ef(){}void eg();}/* Prevent g and eg from being optimized away. */void h(){ g(); eg();}
Kompilieren Sie mit der GCC 4.8 Linux ELF- Ausgabe:
g++-c main.cpp
Dekompilieren Sie die Symboltabelle:
readelf -s main.o
Die Ausgabe enthält:
Num:ValueSizeTypeBindVisNdxName8:00000000000000006 FUNC GLOBAL DEFAULT 1 _Z1fv
9:00000000000000066 FUNC GLOBAL DEFAULT 1 ef
10:000000000000000c16 FUNC GLOBAL DEFAULT 1 _Z1hv
11:00000000000000000 NOTYPE GLOBAL DEFAULT UND _Z1gv
12:00000000000000000 NOTYPE GLOBAL DEFAULT UND eg
Deutung
Wir sehen das:
efund egwurden in Symbolen mit dem gleichen Namen wie im Code gespeichert
Die anderen Symbole wurden verstümmelt. Lassen Sie uns sie entwirren:
Schlussfolgerung: Beide der folgenden Symboltypen wurden nicht entstellt:
definiert
deklariert, aber undefiniert ( Ndx = UND), zur Verknüpfung oder Laufzeit aus einer anderen Objektdatei bereitzustellen
Sie benötigen also extern "C"beides, wenn Sie anrufen:
C aus C ++: Sagen Sie g++, dass Sie entwirrte Symbole erwarten sollen, die von erzeugt werdengcc
C ++ aus C: g++Weisen Sie an, nicht verschränkte Symbole für gccdie Verwendung zu generieren
Dinge, die in extern C nicht funktionieren
Es wird offensichtlich, dass jede C ++ - Funktion, die eine Namensveränderung erfordert, im Inneren nicht funktioniert extern C:
extern"C"{// Overloading.// error: declaration of C function ‘void f(int)’ conflicts withvoid f();void f(int i);// Templates.// error: template with C linkagetemplate<class C>void f(C i){}}
Das Aufrufen von C aus C ++ ist ziemlich einfach: Jede C-Funktion verfügt nur über ein mögliches nicht entstelltes Symbol, sodass keine zusätzliche Arbeit erforderlich ist.
#ifndef C_H
#define C_H
/* This ifdef allows the header to be used from both C and C++. */#ifdef __cplusplus
extern"C"{#endifint f();#ifdef __cplusplus
}#endif#endif
Das Aufrufen von C ++ von ist etwas schwieriger: Wir müssen manuell nicht entstellte Versionen jeder Funktion erstellen, die wir verfügbar machen möchten.
Hier zeigen wir, wie C ++ - Funktionsüberladungen C ausgesetzt werden.
#ifndef CPP_H
#define CPP_H
#ifdef __cplusplus
// C cannot see these overloaded prototypes, or else it would get confused.int f(int i);int f(float i);extern"C"{#endifint f_int(int i);int f_float(float i);#ifdef __cplusplus
}#endif#endif
cpp.cpp
#include"cpp.h"int f(int i){return i +1;}int f(float i){return i +2;}int f_int(int i){return f(i);}int f_float(float i){return f(i);}
#ifdef __cplusplus extern "C" { #endif
Wenn sie aus einer C ++ - Datei aufgenommen werden, werden sie weiterhin als C-Header behandelt.extern "C" legt fest, wie Symbole in der generierten Objektdatei benannt werden sollen. Wenn eine Funktion ohne externes "C" deklariert wird, verwendet der Symbolname in der Objektdatei die C ++ - Namensverknüpfung. Hier ist ein Beispiel.
Gegeben test.C wie folgt:
Das Kompilieren und Auflisten von Symbolen in der Objektdatei ergibt:
Die foo-Funktion heißt eigentlich "_Z3foov". Diese Zeichenfolge enthält unter anderem Typinformationen für den Rückgabetyp und die Parameter. Wenn Sie stattdessen test.C wie folgt schreiben:
Dann kompilieren und betrachten Sie Symbole:
Sie erhalten eine C-Verknüpfung. Der Name der "foo" -Funktion in der Objektdatei ist nur "foo" und enthält nicht alle ausgefallenen Typinformationen, die aus der Namensverfälschung stammen.
Sie fügen in der Regel einen Header in extern "C" {} ein, wenn der dazugehörige Code mit einem C-Compiler kompiliert wurde, Sie ihn jedoch aus C ++ aufrufen möchten. Wenn Sie dies tun, teilen Sie dem Compiler mit, dass alle Deklarationen im Header die C-Verknüpfung verwenden. Wenn Sie Ihren Code verknüpfen, enthalten Ihre .o-Dateien Verweise auf "foo", nicht auf "_Z3fooblah", was hoffentlich mit dem übereinstimmt, mit dem Sie in der Bibliothek verknüpfen.
Die meisten modernen Bibliotheken werden solche Header schützen, sodass Symbole mit der richtigen Verknüpfung deklariert werden. zB in vielen Standard-Headern finden Sie:
Dadurch wird sichergestellt, dass die Symbole in Ihrer Objektdatei mit denen in der C-Bibliothek übereinstimmen, wenn C ++ - Code den Header enthält. Sie sollten nur externes "C" {} um Ihren C-Header setzen müssen, wenn dieser alt ist und diese Wachen noch nicht hat.
quelle
In C ++ können Sie verschiedene Entitäten haben, die einen Namen gemeinsam haben. Zum Beispiel ist hier eine Liste von Funktionen, die alle foo heißen :
A::foo()
B::foo()
C::foo(int)
C::foo(std::string)
Um zwischen allen zu unterscheiden, erstellt der C ++ - Compiler in einem Prozess, der als Namensverknüpfung oder -dekoration bezeichnet wird, eindeutige Namen für jeden Namen. C-Compiler tun dies nicht. Darüber hinaus kann jeder C ++ - Compiler dies auf andere Weise tun.
extern "C" weist den C ++ - Compiler an, keine Namensänderung für den Code in geschweiften Klammern vorzunehmen. Auf diese Weise können Sie C-Funktionen in C ++ aufrufen.
quelle
Dies hängt mit der Art und Weise zusammen, wie die verschiedenen Compiler das Namens-Mangling durchführen. Ein C ++ - Compiler entstellt den Namen eines aus der Header-Datei exportierten Symbols auf völlig andere Weise als ein C-Compiler. Wenn Sie also versuchen, eine Verknüpfung herzustellen, wird ein Linkerfehler angezeigt, der besagt, dass Symbole fehlen.
Um dies zu beheben, weisen wir den C ++ - Compiler an, im "C" -Modus ausgeführt zu werden, damit die Namensverwaltung auf die gleiche Weise wie beim C-Compiler ausgeführt wird. Danach werden die Linkerfehler behoben.
quelle
C und C ++ haben unterschiedliche Regeln für Symbolnamen. Mit Symbolen weiß der Linker, dass der Aufruf der Funktion "openBankAccount" in einer vom Compiler erstellten Objektdatei eine Referenz auf die Funktion ist, die Sie "openBankAccount" in einer anderen Objektdatei genannt haben, die von derselben (oder kompatiblen) aus einer anderen Quelldatei erstellt wurde. Compiler. Auf diese Weise können Sie ein Programm aus mehr als einer Quelldatei erstellen. Dies ist eine Erleichterung bei der Arbeit an einem großen Projekt.
In C ist die Regel sehr einfach, Symbole befinden sich sowieso alle in einem einzigen Namensraum. Die Ganzzahl "socks" wird also als "socks" und die Funktion count_socks als "count_socks" gespeichert.
Mit dieser einfachen Symbolbenennungsregel wurden Linker für C und andere Sprachen wie C erstellt. Symbole im Linker sind also nur einfache Zeichenfolgen.
In C ++ können Sie in der Sprache Namespaces, Polymorphismus und verschiedene andere Dinge verwenden, die mit einer so einfachen Regel in Konflikt stehen. Alle sechs polymorphen Funktionen mit der Bezeichnung "Hinzufügen" müssen unterschiedliche Symbole haben. Andernfalls wird das falsche von anderen Objektdateien verwendet. Dies geschieht durch "Zerfleischen" (das ist ein technischer Begriff) der Namen von Symbolen.
Wenn Sie C ++ - Code mit C-Bibliotheken oder Code verknüpfen, benötigen Sie externes "C" für alles, was in C geschrieben ist, z. B. Header-Dateien für die C-Bibliotheken, um Ihrem C ++ - Compiler mitzuteilen, dass diese Symbolnamen nicht entstellt werden dürfen, während der Rest von Ihr C ++ - Code muss natürlich entstellt sein, sonst funktioniert es nicht.
quelle
Wenn Sie C-Bibliotheken mit C ++ - Objektdateien verknüpfen
C und C ++ verwenden unterschiedliche Schemata für die Symbolbenennung. Dies weist den Linker an, das C-Schema zu verwenden, wenn er in der angegebenen Bibliothek verknüpft.
Mit dem C-Namensschema können Sie auf Symbole im C-Stil verweisen. Andernfalls würde der Linker Symbole im C ++ - Stil ausprobieren, die nicht funktionieren würden.
quelle
Sie sollten extern "C" immer dann verwenden, wenn Sie einen Header einfügen, der Funktionen definiert, die sich in einer Datei befinden, die von einem C-Compiler kompiliert und in einer C ++ - Datei verwendet wird. (Viele Standard-C-Bibliotheken enthalten diese Prüfung möglicherweise in ihren Headern, um sie für den Entwickler einfacher zu machen.)
Wenn Sie beispielsweise ein Projekt mit 3 Dateien, util.c, util.h und main.cpp, haben und sowohl die .c- als auch die .cpp-Dateien mit dem C ++ - Compiler (g ++, cc usw.) kompiliert werden, ist dies nicht der Fall. Es wird nicht wirklich benötigt und kann sogar Linkerfehler verursachen. Wenn Ihr Erstellungsprozess einen regulären C-Compiler für util.c verwendet, müssen Sie externes "C" verwenden, wenn Sie util.h einschließen.
Was passiert ist, dass C ++ die Parameter der Funktion in ihrem Namen codiert. So funktioniert Funktionsüberladung. Alles, was einer C-Funktion passieren kann, ist das Hinzufügen eines Unterstrichs ("_") am Anfang des Namens. Ohne externes "C" sucht der Linker nach einer Funktion namens DoSomething @@ int @ float (), wenn der tatsächliche Name der Funktion _DoSomething () oder nur DoSomething () lautet.
Die Verwendung von externem "C" löst das obige Problem, indem dem C ++ - Compiler mitgeteilt wird, dass er nach einer Funktion suchen soll, die der C-Namenskonvention anstelle der C ++ - folgt.
quelle
Der C ++ - Compiler erstellt Symbolnamen anders als der C-Compiler. Wenn Sie also versuchen, eine Funktion aufzurufen, die sich in einer C-Datei befindet, die als C-Code kompiliert wurde, müssen Sie dem C ++ - Compiler mitteilen, dass die Symbolnamen, die aufgelöst werden sollen, anders aussehen als standardmäßig. Andernfalls schlägt der Verknüpfungsschritt fehl.
quelle
Das
extern "C" {}
Konstrukt weist den Compiler an, die in geschweiften Klammern deklarierten Namen nicht zu entstellen. Normalerweise "erweitert" der C ++ - Compiler die Funktionsnamen so, dass sie Typinformationen über Argumente und den Rückgabewert codieren. Dies nennt man den verstümmelten Namen . Dasextern "C"
Konstrukt verhindert das Zerfleischen.Es wird normalerweise verwendet, wenn C ++ - Code eine C-Sprachbibliothek aufrufen muss. Es kann auch verwendet werden, wenn eine C ++ - Funktion (z. B. aus einer DLL) C-Clients zur Verfügung gestellt wird.
quelle
Dies wird verwendet, um Probleme mit der Namensveränderung zu beheben. extern C bedeutet, dass sich die Funktionen in einer "flachen" API im C-Stil befinden.
quelle
Dekompilieren Sie eine
g++
generierte Binärdatei, um zu sehen, was los istUm zu verstehen, warum dies
extern
erforderlich ist, müssen Sie am besten anhand eines Beispiels verstehen, was in den Objektdateien im Detail vor sich geht:main.cpp
Kompilieren Sie mit der GCC 4.8 Linux ELF- Ausgabe:
Dekompilieren Sie die Symboltabelle:
Die Ausgabe enthält:
Deutung
Wir sehen das:
ef
undeg
wurden in Symbolen mit dem gleichen Namen wie im Code gespeichertDie anderen Symbole wurden verstümmelt. Lassen Sie uns sie entwirren:
Schlussfolgerung: Beide der folgenden Symboltypen wurden nicht entstellt:
Ndx = UND
), zur Verknüpfung oder Laufzeit aus einer anderen Objektdatei bereitzustellenSie benötigen also
extern "C"
beides, wenn Sie anrufen:g++
, dass Sie entwirrte Symbole erwarten sollen, die von erzeugt werdengcc
g++
Weisen Sie an, nicht verschränkte Symbole fürgcc
die Verwendung zu generierenDinge, die in extern C nicht funktionieren
Es wird offensichtlich, dass jede C ++ - Funktion, die eine Namensveränderung erfordert, im Inneren nicht funktioniert
extern C
:Minimal ausführbares C aus C ++ - Beispiel
Der Vollständigkeit halber und für die Neulinge da draußen siehe auch: Wie verwende ich C-Quelldateien in einem C ++ - Projekt?
Das Aufrufen von C aus C ++ ist ziemlich einfach: Jede C-Funktion verfügt nur über ein mögliches nicht entstelltes Symbol, sodass keine zusätzliche Arbeit erforderlich ist.
main.cpp
CH
cc
Lauf:
Ohne
extern "C"
den Link scheitert mit:weil
g++
erwartet, eine verstümmelte zu findenf
, diegcc
nicht produziert hat.Beispiel auf GitHub .
Minimal ausführbares C ++ aus C-Beispiel
Das Aufrufen von C ++ von ist etwas schwieriger: Wir müssen manuell nicht entstellte Versionen jeder Funktion erstellen, die wir verfügbar machen möchten.
Hier zeigen wir, wie C ++ - Funktionsüberladungen C ausgesetzt werden.
Haupt c
cpp.h.
cpp.cpp
Lauf:
Ohne
extern "C"
scheitert es mit:weil
g++
erzeugte verstümmelte Symbole, diegcc
nicht finden können.Beispiel auf GitHub .
Getestet in Ubuntu 18.04.
quelle