將extern "C"
放入C ++代碼到底能作什麼? c#
例如: 函數
extern "C" { void foo(); }
extern「 C」旨在由C ++編譯器識別,並通知編譯器所註明的功能已(或將要)以C樣式進行編譯。 這樣,在連接時,它會連接到C中正確版本的函數。 佈局
它通知C ++編譯器在連接時以C樣式查找這些函數的名稱,由於在連接階段,用C和C ++編譯的函數的名稱不一樣。 spa
它以一種可從C調用該函數的方式更改函數的連接。實際上,這意味着函數名稱不會被修飾 。 code
extern「 C」使C ++中的函數名稱具備'C'連接(編譯器不會更更名稱),以便客戶端C代碼可使用'C'兼容的頭文件連接到(即便用)您的函數,該頭文件僅包含函數的聲明。 函數定義以二進制格式(由C ++編譯器編譯)包含,客戶端「 C」連接器隨後將使用「 C」名稱連接至該二進制文件。 對象
因爲C ++具備重載的函數名,而C沒有重載,所以C ++編譯器不能僅使用函數名做爲要連接的惟一ID,所以它經過添加有關自變量的信息來破壞名稱。 AC編譯器不須要處理名稱,由於您不能在C中重載函數名稱。當您聲明函數在C ++中具備外部「 C」連接時,C ++編譯器不會將參數/參數類型信息添加到用於連鎖。 ip
衆所周知,您能夠顯式地爲每一個單獨的聲明/定義指定「 C」連接,也可使用一個塊對一系列聲明/定義進行分組以具備必定的連接: 字符串
extern "C" void foo(int); extern "C" { void g(char); int i; }
若是您關心技術方面的問題,它們會在C ++ 03標準的7.5節中列出,此處是一個簡短的摘要(着重於外部「 C」): get
在每一個C ++程序中,全部非靜態函數在二進制文件中均以符號表示。 這些符號是特殊的文本字符串,可惟一標識程序中的功能。 編譯器
在C語言中,符號名稱與函數名稱相同。 這是可能的,由於在C中,沒有兩個非靜態函數能夠具備相同的名稱。
因爲C ++容許重載,而且具備C所不容許的許多功能(例如類,成員函數,異常規範),所以沒法簡單地將函數名用做符號名。 爲了解決這個問題,C ++使用了所謂的名稱修飾,將函數名稱和全部必要的信息(例如參數的數量和大小)轉換爲一些僅由編譯器和連接器處理的怪異字符串。
所以,若是將函數指定爲extern C,則編譯器不會對其進行名稱修飾,而且可使用其符號名做爲函數名稱直接對其進行訪問。
這在使用dlsym()
和dlopen()
調用此類函數時很是方便。