1. 在C++中調用C:使用extern C則是告訴編譯器依照C的方式來編譯封裝接口,當然接口函數裡面的C++語法還是按C++方式編譯。
包裝(wrapper)
2. 在C中調用C++:extern C 的作用是:讓C++連接器找調用函數的符號時采用C的方式
注意這裡的C調用C++或者C++調用C意思是.c文件中調用.cpp文件中代碼,或者相反。
集成開發環境如VC++6.0或者vs都是以文件後綴來區別當前要編譯的是C代碼還是C++代碼,然後采用響應的編譯、調用協議等。
使用extern C 主要是因為C編譯器編譯函數時不帶參數的類型信息,只包含函數的符號名字。如
int foo( float x )
C編譯器會將此函數編譯成類似_foo的符號,C連接器只要找到了調用函數的符號,就認為連接成功。
而C++編譯器為了實現函數重載,會在編譯時帶上函數的參數信息。如它可以把上面的函數編譯成類似於_foo_float這樣的符號。
所以,C調用C++,使用extern C則是告訴編譯器依照C的方式來編譯封裝接口,當然接口函數裡面的C++語法還是按C++方式編譯。
如:1 普通函數
// C++ Code
extern C int foo( int x );
int foo( int x )
{
//...
}
這樣,編譯器會將foo函數編譯成類似_foo符號,而不會編譯成類似_foo_int符號
則C可以這樣調用C++函數
// C Code
int foo( int x );
void cc( int x )
{
foo( x );
//...
}
2 如果想調用重載的C++函數,則須封裝單獨的接口共C調用。
如
// C++ Code
void foo( int x );
void foo( float x );
extern C void foo_i( int x )
{
foo( x );
}
extern C void foo_f( float x )
{
foo( x );
}
則C中可這樣調用
// C Code
void foo_i( int x );
void foo_f( float x );
void ccc( int x1, float x2 )
{
foo_i( x1 );
foo_f( x2 );
// ...
}
3 C中想調用C++中的成員函數(包括虛函數),則需要提供一個簡單的包裝(wrapper)。
例如: // C++ code:
class C
{
...
virtual double f(int);
};
extern C double call_C_f(C* p, int i) // wrapper function
{
return p->f(i);
}
然後,你就可以這樣調用 C::f():
//C code
double call_C_f(struct C* p, int i);//聲明
void ccc(struct C* p, int i)
{
double d=call_C_f(p,i);
...
}
問題:參數struct C* p從哪裡來,即怎麼在C中定義C++對象,其實上面只是說了思想,真實的c中使用C++類需要把原來的類都封裝一下,參看下面的文章
http://blog.csdn.net/caspiansea/article/details/9676153
而C++調用C,extern C 的作用是:讓C++連接器找調用函數的符號時采用C的方式 如:
// C Code
void foo( int x );
C++這樣調用C函數
// C++ Code
extern C void foo( int x );
就是讓C++連接器能過類似於_foo來查找此函數,而非類似於_foo_int這樣的符號。
時常在cpp的代碼之中看到這樣的代碼: 特別是C ++中引入C的頭文件,這些C頭文件中出現很多如下代碼。
#ifdef __cplusplus extern C { #endif
//一段代碼
#ifdef __cplusplus } #endif
其中__cplusplus是C++編譯器的保留宏定義.就是說C++編譯器認為這個宏已經定義了.所以關鍵是extern C {}extern C是告訴C++編譯器件括號裡的東東是按照C的obj文件格式編譯的,要連接的話按照C的命名規則去找.要明白為何使用extern C,還得從cpp中對函數的重載處理開始說起。在c++中,為了支持重載機制,在編譯生成的匯編碼中,要對函數的名字進行一些處理,加入比如函數的返回類型等等.而在C中,只是簡單的函數名字而已,不會加入其他的信息.也就是說:C++和C對產生的函數名字的處理是不一樣的.
明白了加入與不加入extern C之後對函數名稱產生的影響,我們繼續我們的討論:為什麼需要使用extern C呢?C++之父在設計C++之時,考慮到當時已經存在了大量的C代碼,為了支持原來的C代碼和已經寫好C庫,需要在C++中盡可能的支持C,而extern C就是其中的一個策略。
試想這樣的情況:一個庫文件已經用C寫好了而且運行得很良好,這個時候我們需要使用這個庫文件,但是我們需要使用C++來寫這個新的代碼。如果這個代碼使用的是C++的方式鏈接這個C庫文件的話,那麼就會出現鏈接錯誤.
現在我們有了一個C庫文件,它的頭文件是f.h,產生的lib文件是f.lib,那麼我們如果要在C++中使用這個庫文件,我們需要這樣寫:
extern C {
#include f.h
}