2016-04-22 9 views
6

Aby użyć kodu C++ w pliku C, przeczytałem, że możemy po prostu zrobić extern "C" { (where the c++ code goes here)}, ale kiedy próbuję drukować coś za pomocą cout, ciągle dostaję błąd, ponieważ nie rozpoznaje biblioteki. Myślę, że jestem po prostu zdezorientowany, w jaki sposób zewnętrzne "C" pozwala ci na użycie kodu C++ w C.w jaki sposób extern "C" zezwala na kod C++ w pliku C?

Odpowiedz

12

Jest odwrotnie. Możesz użyć zewnętrznego C, aby dodać kod, który chcesz skompilować jako kod C przy użyciu kompilatora C++.

O ile czegoś mi brakuje, nie można skompilować kodu C++ za pomocą kompilatora C.

9

Konstrukcja extern "C" jest składnią specyficzną dla C++, żaden kompilator języka C go nie zrozumie.

Dlatego prawie zawsze zobaczyć go w połączeniu z pewnym conditional compilation jak

#ifdef __cplusplus 
extern "C" { 
#endif 
... 
#ifdef __cplusplus 
} 
#endif 

Co extern "C"robi jest po prostu hamować name mangling co oznacza, że ​​symbole zdefiniowane w C++ plik źródłowy może być używany w program C.

Pozwala to na posiadanie projektu z mieszanymi źródłami C i C++, a źródło C może wywoływać funkcje C++, które zostały zdefiniowane jako extern "C".

Bardzo prosty i głupi przykład, żeby pokazać punkt:

Powiedzmy, że mamy plik źródłowy C, skompilowany z kompilatora C:

#include <stdio.h> 

void foo(void); // Declare function prototype, so it can be called 

int main(void) 
{ 
    printf("Calling foo...\n"); 
    foo(); 
    printf("Done\n"); 

    return 0; 
} 

wtedy mamy C++ plik źródłowy dla foo funkcję: plik źródłowy

#include <iostream> 

extern "C" void foo() 
{ 
    std::cout << "Hello from foo\n"; 
} 

C jest skompilowany z kompilatora C i C++ plik źródłowy jest kompilowany z C++. Następnie dwa pliki obiektów są ze sobą połączone, tworząc plik wykonywalny. Ponieważ foo został zdefiniowany jako extern "C", jego nazwa symbolu w pliku obiektowym nie jest zniekształcona, a linker może rozwiązać odniesienie z pliku obiektu utworzonego przez kompilator C.

Działa również w drugim kierunku. Ponieważ symbole w C nie są zniekształcone, kompilator C++ musi o tym wiedzieć, a to się dzieje przez deklarowanie symboli C extern "C", zwykle w pliku nagłówkowym z użyciem kompilacji warunkowej, jak pokazano powyżej. Jeśli nie zostałby użyty extern "C", kompilator C++ pomyślałby, że symbole są symbolami C++ i łączą się z nazwami prowadzącymi do problemów z linkerem, gdy linker nie może znaleźć zniekształconych symboli.

Równie głupi przykład: Pierwszy plik C++ źródło

#include <iostream> 

extern "C" void bar(); // Declare function prototype as an unmangled symbol 

int main() 
{ 
    std::cout << "Calling bar...\n"; 
    bar(); 
} 

Następnie plik źródłowy C

#include <stdio.h> 

void bar(void) 
{ 
    printf("Inside bar\n"); 
} 
+2

Jest coś więcej niż "extern" C "" niż blokowanie wymazywania nazw. Robi inne rzeczy, aby umożliwić również połączenie między C i C++. – Peter

0

extern "C" jest sposobem na wprowadzenie kodu C w kod C++. Mówiąc dokładniej, nakazuje kompilatorowi wyłączenie niektórych funkcji, takich jak przeciążanie funkcji, aby wyłączyć funkcję wymazywania nazw.W C++ prostej funkcji, takich jak:

int add(int a, int b) { 
    return a+b; 
} 

rzeczywiście trochę ostry nazwę w bibliotece do oznaczania parametrów tak, że jeśli można zdefiniować inną funkcję jak:

double add(double a, double b) { 
    return a+b; 
} 

że wie, który z nich zadzwonić . Nie chcesz tego, jeśli próbujesz korzystać z biblioteki C i do tego właśnie służy extern "C". Wszystko to jest powiedziane, extern "C" nie zezwala na C++ w programie C.

0

Wyeksportowane symbole C++, jako wygenerowane przeze mnie kompilator, są zmanipulowane w celu dołączenia dodatkowych informacji o typie symbolu do łącznika.

zatem następujące funkcje przeciążone byłyby rozróżnialne przez łącznik w C++, ale nie C:

  • int fn();
  • int fn(int);
  • int fn(char*);
  • int fn(char*) const;
  • int fn(const char*);

Składnia extern "C" { ... } pozwala na symbole (lub odniesienia do symboli C) określone w kodu C++, bez użycia zasady mangling. Pozwala to na połączenie takiego kodu w C z bibliotekami C.