2015-03-11 8 views
12
namespace someNameSpace { 
    extern "C" void doSomething() 
     { 
      someOperations(); 
     } 
} 

Ich möchte doSomething() in C++ und C-Umgebung ausführen.extern "C" Verknüpfung innerhalb C++ - Namespace?

Ist someNameSpace immer noch verkapseln doSomething(), wenn ich es extern "C" Verknüpfung ausgesetzt?

Gibt es eine gute Möglichkeit, Funktionen zwischen C++ und C zu teilen, während die Verschmutzung von globalen Namespaces auf C++ - Seite vermieden wird?

Bearbeiten: Da dieser Code hauptsächlich im C++ - Modus verwendet wird, während die C-Verknüpfung nur für den Test verwendet wird, denke ich, dass dies ein besserer Weg ist.

namespace someNameSpace { 
    #ifdef COMPILE_FOR_C_LINKAGE 
    extern "C" 
    #else 
    extern "C++" 
    #endif 
    { 
     void doSomething() 
      { 
       someOperations(); 
      } 
    } 
} 
+0

Haben Sie versucht, es in einem C-Programm zu benutzen? Wenn ja, was ist passiert? –

+0

@RyanJ Ja, ich habe es versucht, es kompiliert und verbindet sich gut in C++ und C. Ich habe es noch nicht ausgeführt. – user3528438

Antwort

10

Ihr Code funktioniert, aber man sollte aufpassen, dass alle Funktionen, die extern "C" Verknüpfung teilen sich den gleichen Raum der Namen haben, aber das ist nicht mit dem C++ Begriff des „Namensraum“ verwechselt werden: Ihre Funktion ist wirklich someNameSpace::doSomething , aber Sie können keine andere extern "C" Funktion mit dem unqualifizierten Namen doSomething in einem anderen Namespace haben.

Siehe 7.5/6:

Höchstens eine Funktion mit einem bestimmten Namen der Sprache C-Bindung hat. Zwei Deklarationen für eine Funktion mit C-Sprachverknüpfung mit dem gleichen Funktionsnamen (Ignorieren der Namespace-Namen, die es qualifizieren), dass in verschiedenen Namespacebereichen angezeigt werden, beziehen sich auf die gleiche Funktion. Zwei Deklarationen für eine Variable mit C Sprachverknüpfung mit demselben Namen (die Namespace-Namen ignorieren, die es qualifizieren), die in anderen Namespacebereichen angezeigt werden, beziehen sich auf die gleiche Variable. Eine Entität mit einer C-Sprachverknüpfung darf nicht mit denselben Namen wie eine Variable im globalen Gültigkeitsbereich deklariert werden, es sei denn, beide Deklarationen bezeichnen dieselbe Entität; Keine Diagnose ist erforderlich, wenn die Deklarationen in verschiedenen Übersetzungseinheiten angezeigt werden. Eine Variable mit C-Sprachverknüpfung darf nicht mit dem gleichen Namen wie eine Funktion mit C-Sprachverknüpfung deklariert sein (wobei die Namensraumnamen ignoriert werden, die die jeweiligen Namen qualifizieren); Wenn die Deklarationen in verschiedenen Einheiten angezeigt werden, ist keine Diagnose erforderlich. [Hinweis: Nur eine Definition für eine Entität mit einem bestimmten Namen mit C-Sprache-Verknüpfung möglicherweise in das Programm angezeigt (siehe 3.2); Dies bedeutet, dass eine solche Entität nicht in mehr als einem Namespace Bereich definiert werden darf. - Endnote]

Ihr Unternehmen oder globaler Stil Arbiter des Projektes der Lage sein, sollten Sie sich auf einer geeignete Namensrichtlinie für Ihre Code-Basis zu beraten.

+0

Eine Entität mit einer C-Sprachverknüpfung darf nicht mit demselben Namen wie eine Variable im globalen Gültigkeitsbereich deklariert werden, es sei denn, beide Deklarationen bezeichnen dieselbe Entität. ---- Ist das eine Aussage "Entität gegen Variable"? Ich habe mit g ++ 4.3.3 experimentiert und es scheint richtig zu sein.Der Konflikt tritt nur auf, wenn ich eine globale Variable wie "extern int doSomething = 1;" aber es ist in Ordnung, wenn ich ein anderes "extern void doSomething() {}" definiere, solange es keine andere externe C-Verbindung ist. – user3528438

+1

Ihre abschließende Aussage im ersten Absatz ist falsch - Sie KÖNNEN ein anderes "doSomething" in einem anderen Namensraum definiert haben, solange es nicht "extern" C "' ist. –

+0

@ChrisDodd: Ah ja, das habe ich gemeint. Bearbeitet. Vielen Dank! –

2

Gerade Stück Code Verhalten in Kerrek SB Antwort angegeben zu veranschaulichen

#include <iostream> 

namespace C{ 
    void Hello(){ 
     std::cout<<"Hello"<<std::endl; 
    } 
    extern "C" void HelloThere(){ 
     std::cout<<"Hello There from extern \"C\""<<std::endl; 
    } 
} 

extern "C" void HelloThere(); 

int main() { 
    C::Hello(); 
    C::HelloThere(); //Compiles 
    //Hello(); <--- does not compile 
    HelloThere(); //Also compiles and prints the same as C::HelloThere() !!! 

    return 0; 
} 

Live at http://ideone.com/X26wfR