Anhang J

extern "C" Speicherklasse

Eine besondere Form der extern-Anweisung ist die Anweisung extern "C". Sie dient dazu, in einem C++ Programm Funktionen aufzurufen, die mit einem C-Compiler übersetzt wurden. Diese Funktionen müssen als extern "C" Funktionen gekennzeichnet werden.

// Deklaration (nicht Definition!)
// einer C-Funktion
extern "C" void MyCFunc(...);

// Deklarationen von mehreren C-Funktionen
extern "C"
{
   void MyCFunc1(...);
   short MyCFunc2(...);
}

Der Grund, warum C-Funktionen eine gesonderte Behandlung erfordern, ist, dass ein C++-Compiler als Symbolname für eine Funktion nicht nur den Funktionsnamen alleine verwendet (wie ein C-Compiler), sondern zusätzlich die Datentypen der Funktionsparameter mit in den Symbolnamen aufnimmt. Dieses Verhalten des C++-Compilers wird auch als name mangeling bezeichnet. Durch die Anweisung extern "C" wird der C++-Compiler nun angewiesen, als Symbolname für die Funktion nur den Funktionsnamen zu verwenden, genauso wie es ein C-Compiler tut. Warum ein C++-Compiler auch die Parameter mit auswerten muss, das wird beim Überladen von Funktionen ersichtlich.

Haben Sie mehrere C-Funktionen geschrieben, die Sie sowohl unter C als auch unter C++ einsetzen wollen, werden die Funktionsdeklarationen in der Regel in einer Header-Datei zusammengefasst. Damit die C-Funktionen auch von C++ aus aufrufbar sind, sind sie in der Header-Datei als extern "C" Funktionen zu deklarieren. Wird diese Header-Datei nun aber von einem C-Compiler eingelesen, wird dieser eine Fehlermeldung ausgeben, da er die extern "C" Anweisung nicht kennt. Wir könnten nun jeweils eine Header-Datei für den C-Compiler und ein für C++-Compiler erstellen, was aber irgendwann zu Wartungsproblemen führen wird, da immer beide Header-Dateien gleichzeitig angepasst werden müssten. Im Beispiel unten ist eine der Lösungsmöglichkeiten für dieses Problems dargestellt. Ein C++-Compiler definiert ein internes Symbol mit dem Namen __cplusplus (2 Underscore am Anfang!). Und dieses Symbol kann wie unten dargestellt mittels #ifdef...#endif abgefragt werden, um so bedingt die extern "C" Anweisung einzubinden.

#ifdef __cplusplus
extern "C"
{
#endif
   ... // Hier stehen die Funktionsdeklarationen
#ifdef __cplusplus
}
#endif