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

Chcę uruchomić doSomething() zarówno w środowisku C++, jak i C.zewnętrzne powiązanie "C" w przestrzeni nazw C++?

Czy someNameSpace nadal hermetyzuje doSomething(), jeśli wystawię go na połączenie extern "C"?

Czy istnieje dobry sposób na dzielenie się funkcjami między C++ i C, unikając zanieczyszczania globalnej przestrzeni nazw po stronie C++?

Edit: Ponieważ kod ten jest stosowany głównie w C++ tryb, natomiast C podnośnik jest przeznaczony do użytku tylko testowym, to chyba lepszy sposób to zrobić.

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

Próbowałaś go używać w programie C? Jeśli tak, co się stało? –

+0

@RyanJ Tak, próbowałem, kompiluje i łączy dobrze zarówno w C++ i C. Jeszcze go nie uruchomiłem. – user3528438

Odpowiedz

10

Twój kod działa, ale należy wystrzegać, że wszystkie funkcje, które mają extern "C" powiązania udział w tej samej przestrzeni nazw, ale to nie należy mylić z C++ pojęcia „przestrzeni nazw”: Twoja funkcja jest naprawdę someNameSpace::doSomething , ale nie możesz mieć żadnej innej funkcji extern "C" o niekwalifikowanej nazwie doSomething w jakiejkolwiek innej przestrzeni nazw.

Zobacz 7.5/6:

Co najwyżej jednej funkcji z danej nazwy może mieć języka C powiązania. Dwie deklaracje funkcji z łączeniem w języku C o tej samej nazwie funkcji (ignorowanie nazw obszarów, które ją kwalifikują), że pojawiają się w różnych zakresach przestrzeni nazw, odnoszą się do tej samej funkcji. Dwie deklaracje dla zmiennej z C powiązaniami językowymi o tej samej nazwie (ignorując nazwy przestrzeni nazw, które ją kwalifikują), które pojawiają się w różnych zakresach przestrzeni nazw odnoszącej się do , odnoszą się do tej samej zmiennej. Jednostka z połączeniem w języku C nie powinna być zadeklarowana jako o tej samej nazwie, co zmienna o zasięgu globalnym, chyba że oba oświadczenia oznaczają ten sam podmiot; diagnostyka nie jest wymagana, jeśli deklaracje pojawiają się w różnych jednostkach tłumaczeniowych. Zmienna z łączeniem w języku C nie powinna być zadeklarowana z taką samą nazwą jak funkcja z łączeniem w języku C (ignorując nazwy przestrzeni nazw, które kwalifikują odpowiednie nazwy); diagnostyka nie jest wymagana, jeśli deklaracje pojawiają się w różnych jednostkach tłumaczeniowych . [Uwaga: Tylko jedna definicja dla jednostki o danej nazwie z łączeniem w języku C może pojawić się w programie (patrz 3.2); oznacza to, że taki obiekt nie może być zdefiniowany w więcej niż jednym obszarze nazw o zakresie . - koniec uwaga]

powinny być firmowym lub globalne arbitrów stylu projektu stanie doradzić na odpowiedniej polityki nazewnictwa bazy kodu.

+0

Jednostka z połączeniem w języku C nie powinna być deklarowana z tą samą nazwą, co zmienna o zasięgu globalnym, chyba że obie deklaracje oznaczają ten sam podmiot; ---- Czy jest to instrukcja "entity vs variable"? Eksperymentowałem z g ++ 4.3.3 i wydaje się to prawdą.Konflikt występuje tylko wtedy, gdy ponownie deklaruję zmienną globalną, taką jak "extern int doSomething = 1;" ale jest OK, jeśli zdefiniuję inny "extern void doSomething() {}", o ile nie jest to kolejne zewnętrzne powiązanie C. – user3528438

+1

Twoje końcowe stwierdzenie w pierwszym akapicie jest błędne - MOŻESZ mieć inne 'coś \" zdefiniowane w innej przestrzeni nazw, o ile nie jest "zewnętrznym" C "'. –

+0

@ChrisDodd: Ach tak, właśnie o to mi chodziło. Edytowane. Dzięki! –

2

Wystarczy kawałek kodu do zilustrowania zachowań podaną w Kerrek SB odpowiedź

#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

Powiązane problemy