2011-11-03 47 views
5

我知道如何使用extern "C"但是您必須使用它的條件是什麼?何時使用extern「C」?

extern "C"告訴C++編譯器不執行任何名稱重整上 大括號內的代碼。這使您可以在C++中從 調用C函數。

例如:

#include <string.h> 

int main() 
{ 
    char s[] = "Hello"; 
    char d[6]; 

    strcpy_s(d, s); 
} 

雖然這種編譯VC++的罰款。但有時這寫成:

extern "C" { 
#include <string.h> 
} 

我沒有看到這一點。你能舉一個真實的例子,extern "C"是必要的嗎?

+7

而是黑客''避免名字改編的,使用''標題。 –

+0

@AlexandreC:使用''標題絕對不是一個好主意。 ''頭部*不*保證將標識符放置在全局名稱空間中,從而在代碼移動到其他編譯器時破壞依賴於全局名稱空間標識符的代碼。另外,''頭可能並且實際上會將標識符放置在全局名稱空間中,因此理論上也會破壞依賴於無污染全局名稱空間的代碼。 「理論上」雖然過於模糊,至少有一個白癡做到了。所以,不要使用它們。 –

+0

@ AlfP.Steinbach:如果您編寫C++,請使用''。如果你編寫C,使用''和**用C編譯器**編譯你的代碼。混合語言不是一個好主意。 –

回答

4

當您從庫中導出函數時,會出現一個非常常見的用途extern "C"。如果您不禁用C++名稱修改,則可以使庫的客戶非常難以命名您的函數。同樣的,當你走向另一個方向時,當你導入一個已經用C鏈接導出的函數時。

6

您可以使用extern "C"來防止頭文件中的名稱變形,以及您的C++對象文件用於庫或已經編譯時沒有變形的對象。

例如,假設您有一個widget庫,該庫使用C編譯器進行編譯,以使其發佈的接口不受損壞。

如果在代碼中包含頭文件,它會假定的名稱是,並且這些損壞的版本是您要鏈接器查找的內容。

但是,由於您會要求類似[email protected]_float_charptrwidget圖書館將只發布function,您將遇到問題。

但是,如果包括它:

extern "C" { 
    #include "widget.h" 
} 

你的編譯器會知道它應儘量選用function,非錯位版本。

這就是爲什麼,在對C東西頭文件意指包括用C _or C++程序,你會看到的東西,如:

#ifdef __cplusplus 
    extern "C" { 
#endif 

// Everything here works for both C and C++ compilers. 

#ifdef __cplusplus 
    } 
#endif 

如果您使用的是C編譯器,包括這一點,#ifdef線將導致extern "C"東西消失。對於C++編譯器(其中__cplusplus已定義),所有內容都將不受損壞。

+0

爲什麼還有第二個'#ifdef __cplusplus'? – user103214

+0

@ user974191:用於右大括號,否則大括號將不平衡。 – paxdiablo

1

當您用C寫的庫鏈接時,告知編譯器不要裝飾名稱,以便鏈接器可以找到函數。在C++函數名稱等中有鏈接器的信息,例如參數名稱中包含的參數類型和大小。

1

如果您正在生成一個二進制庫A,該二進制庫A公開了您想要從二進制B調用的函數。

想象一下A是A.dll而B是B.exe,並且您在Windows系統上。

C++沒有描述B的知道如何調用A的二進制佈局。通常,這個問題通過使用相同的編譯器生成A和B來解決。如果您想要更通用的解決方案,請使用extern關鍵字。這以C方式公開該功能。 C確實描述了一種二進制格式,以便來自不同編譯器的不同二進制文件可以相互交談。

參見: http://en.wikipedia.org/wiki/Application_binary_interface http://en.wikipedia.org/wiki/Name_mangling#Name_mangling_in_C.2B.2B

1

如果,你的C++代碼中,你#include一個外部庫(在C語言編寫的)頭,如果功能有沒有宣佈extern "C"他們不會工作(你在鏈接時會得到未定義的參考)。

但這些天來,人們編碼C庫,並提供頭文件你會知道,而且經常把extern "C"在他們的頭文件(與#ifdef __cplusplus適當保護)

也許有更好的方式來了解是使用(假設你有一個Linux系統)nm實用程序來顯示庫或可執行文件中使用的(unmangled)名稱。

3

下面是一個具體的事例破解的例子,需要修復extern "C"

module.h

int f(int arg); 

module.c

int f(int arg) { 
    return arg + 1; 
} 

main.cpp

#include "module.h" 

int main() { 
    f(42); 
} 

因爲我混合使用C和C++,所以它不會鏈接(兩個目標文件,只有一個會知道其C++錯位名稱下的f)。

也許是爲了解決這個問題最徹底的方法是通過使頭文件與C和C++兼容:

module.h

#ifdef __cplusplus 
    extern "C" { 
#endif 

int f(int arg); 

#ifdef __cplusplus 
    } 
#endif 
+0

+1這解釋了我在找什麼。 – user103214