2016-04-22 26 views
6

爲了在C文件中使用C++代碼,我讀了我們可以只做extern "C" { (where the c++ code goes here)},但是當我嘗試使用cout打印某些內容時,我不斷收到錯誤,因爲它不識別該庫。我認爲我只是困惑於如何extern「C」允許您使用C++中的C++代碼。extern「C」如何在C文件中允許C++代碼?

回答

12

正好相反。您可以使用extern C使用C++編譯器將您想編譯的代碼添加爲C代碼。

除非我遺漏了一些不能用C編譯器編譯C++代碼的東西。

9

extern "C"構造是C++特有的語法,C編譯器不會理解它。

這就是爲什麼你幾乎總是看到它與一些conditional compilation配對像

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

什麼extern "C"確實僅僅是爲了抑制name mangling這意味着在C定義的符號++源文件中可以使用一個C程序。

這允許您使用混合C和C++源的項目,並且C源可以調用已定義爲extern "C"的C++函數。

很簡單,愚蠢的,例如,是想說明一點:

假設我們有一個C源文件,用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; 
} 

然後我們有一個C++源文件爲foo功能:

#include <iostream> 

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

的C源文件編譯與C編譯器,以及C++源文件與C++編譯器編譯。然後將這兩個目標文件鏈接在一起形成可執行程序。因爲foo被定義爲extern "C"它在對象文件中的符號名稱沒有被損壞,並且鏈接器可以解析由C編譯器創建的對象文件中的引用。

它也適用於其他方向。因爲C中的符號沒有被破壞,所以C++編譯器需要知道這一點,這是通過聲明C符號extern "C"完成的,通常在頭文件中使用如上所示的條件編譯。如果沒有使用extern "C",則C++編譯器會認爲這些符號是C++符號,並且在鏈接程序無法找到損壞的符號時導致鏈接器問題的名稱被破壞。

同樣笨例如:首先一個C++源文件

#include <iostream> 

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

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

然後C源文件

#include <stdio.h> 

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

「extern」C「'比抑制名稱變形還要多一點。它還做了其他事情來允許C和C++之間的接口。 – Peter

0

extern "C"是把C代碼在C++代碼的一種方法。更具體地說,它告訴編譯器禁用某些功能,如函數重載,這樣它也可以關閉名稱重組。在C++是一個簡單的功能:

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

在圖書館真正能拿到一些時髦的名字來表示的參數,這樣,如果你這樣定義的另一個功能:

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

它知道調用哪一個。如果你正在嘗試使用C庫,那麼你不需要這些,這就是extern "C"的用途。所有這一切都說,extern "C"不允許C程序中的C++。

0

導出的C++符號(如生成的編譯器)是受到損壞以包含有關該符號的附加類型信息到鏈接器。

所以下面的重載函數將是在C連接區分++,但不是C:

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

extern "C" { ... }語法允許在C不使用mangling規則定義++代碼符號(或至C符號的引用)。 這允許這樣的C++代碼與C庫鏈接。