extern是C/C++語言中表明函數和全局變量作用范圍(可見性)的要害字,該要害字告訴編譯器,其聲明的函數和變量可以在本模塊或其它模塊中使用。記住,下列語句: extern int a; 僅僅是一個變量的聲明,其并不是在定義變量a,并未為a分配內存空間。變量a在所有模塊中作為一種全局變量只能被定義一次,否則會出現連接錯誤。
作為一種面向對象的語言,C++支持函數重載,而過程式語言C則不支持。函數被C++編譯后在符號庫中的名字與C語言的不同。例如,假設某個函數的原型為: void foo( int x, int y ); 該函數被C編譯器編譯后在符號庫中的名字為_foo,而C++編譯器則會產生像_foo_int_int之類的名字(不同的編譯器可能生成的名字不同,但是都采用了相同的機制,生成的新名字稱為“mangled name”)。
_foo_int_int這樣的名字包含了函數名、函數參數數量及類型信息,C++就是靠這種機制來實現函數重載的。例如,在C++中,函數void foo( int x, int y )與void foo( int x, float y )編譯生成的符號是不相同的,后者為_foo_int_float。
筆者編寫的C++引用C函數例子工程中包含的三個文件的源代碼如下: /* c語言頭文件:cExample.h */ #ifndef C_EXAMPLE_H #define C_EXAMPLE_H extern int add(int x,int y); #endif /* c語言實現文件:cExample.c */ #include "cExample.h" int add( int x, int y ) { return x + y; } // c++實現文件,調用add:cppFile.cpp extern "C" { #include "cExample.h" } int main(int argc, char* argv[]) { add(2,3); return 0; } 假如C++調用一個C語言編寫的.DLL時,當包括.DLL的頭文件或聲明接口函數時,應加extern "C" { }。
(2)在C中引用C++語言中的函數和變量時,C++的頭文件需添加extern "C",但是在C語言中不能直接引用聲明了extern "C"的該頭文件,應該僅將C文件中將C++中定義的extern "C"函數聲明為extern類型。 筆者編寫的C引用C++函數例子工程中包含的三個文件的源代碼如下: //C++頭文件 cppExample.h #ifndef CPP_EXAMPLE_H #define CPP_EXAMPLE_H extern "C" int add( int x, int y ); #endif //C++實現文件 cppExample.cpp #include "cppExample.h" int add( int x, int y ) { return x + y; } /* C實現文件 cFile.c /* 這樣會編譯出錯:#include "cExample.h" */
extern int add( int x, int y ); int main( int argc, char* argv[] ) { add( 2, 3 ); return 0; } 假如深入理解了第3節中所闡述的extern "C"在編譯和連接階段發揮的作用,就能真正理解本節所闡述的從C++引用C函數和C引用C++函數的慣用法。對第4節給出的示例代碼,需要非凡留意各個細節。