標籤:
在項目中融合C和C++有時是不可避免的,在調用對方的功能函數的時候,或許會出現這樣那樣的問題。
近來在主程式是C語言,而調用C++功能函數的時候,C++的*.h標頭檔都能找到,功能函數也都定義了,最重要的是,單獨編譯C++的時候完全沒有問題,
但當用主程式的C調用C++的功能函數時總是提示該函數未定義(undefined)。這是什麼問題?如何解決?
關鍵點在這裡:我們就靠在C++的*.h和*.cpp的頭尾加入下面代碼才得以解決問題。
#ifdef __cplusplus
extern "C" {
#endif
//一段代碼
#ifdef __cplusplus
}
#endif
1、#ifdef _cplusplus/#endif _cplusplus及發散
其中 __cplusplus是cpp中的自訂宏,很明顯#ifdef/#endif、#ifndef/#endif用於條件編譯,
#ifdef _cplusplus/#endif _cplusplus——表示如果定義了宏_cplusplus,就執行#ifdef/#endif之間的語句,否則就不執行。
上面的代碼的含義是 : 如果這是一段cpp的代碼,那麼加入extern "C"{ 和 } 處理其中的代碼。
在這裡為什麼需要#ifdef _cplusplus/#endif _cplusplus呢?因為C語言中不支援extern "C"聲明,如果你明白extern "C"的作用就知道在C中也沒有必要這樣做,這就是條件編譯的作用!在.c檔案中包含了extern "C"時會出現編譯時間錯誤。
2、extern "C"
extern是C/C++語言中表明函數和全域變數作用範圍(可見度)的關鍵字,該關鍵字告訴編譯器,其聲明的函數和變數可以在本模組或其它模組中使用。
通常,在模組的標頭檔中對本模組提供給其它模組引用的函數和全域變數以關鍵字extern聲明。
與extern對應的關鍵字是 static,被它修飾的全域變數和函數只能在本模組中使用。因此,一個函數或變數只可能被本模組使用時,其不可能被extern “C”修飾。
在C++源檔案中的語句前面加上extern "C",表明它按照類C的編譯和串連規約來編譯和串連,而不是C++的編譯的串連規約。這樣在類C的代碼中就可以調用C++的函數or變數等。
還有要說明的是,extern "C"指令僅指定編譯和串連規約,但不影響語義。例如在函式宣告中,指定了extern "C",仍然要遵守C++的類型檢測、參數轉換規則。
3、C和C++互相調用
要明白為何使用extern "C",還得從cpp中對函數的重載處理開始說起。
在c++中,為了支援重載機制,在編譯產生的彙編碼中,要對函數的名字進行一些處理,加入比如函數的傳回型別等等。
而在C中,只是簡單的函數名字而已,不會加入其他的資訊。也就是說,C++和C對產生的函數名字的處理是不一樣的。
加入 extern "C" 聲明的目的是解決C與C++的相互調用的問題。
3.1、C++的編譯和串連
C++是一個物件導向語言(雖不是純粹的物件導向語言),它支援函數的重載,重載這個特性給我們帶來了很大的便利。為了支援函數重載的這個特性,C++編譯器實際上將下面這些重載函數:
void print(int i);
void print(char c);
void print(float f);
void print(char* s);
編譯為:
_print_int
_print_char
_print_float
_pirnt_string
這樣的函數名,來唯一標識每個函數。註:不同的編譯器實現可能不一樣,但是都是利用這種機制。所以當串連是調用print(3)時,它會去尋找_print_int(3)這樣的函數。
下面說個題外話,正是因為這點,重載被認為不是多態,多態是運行時動態綁定(“一種介面多種實現”),如果硬要認為重載是多態,它頂多是編譯時間“多態”。
C++中的變數,編譯也類似,如全域變數可能編譯g_xx,類變數編譯為c_xx等。串連是也是按照這種機制去尋找相應的變數。
3.2、C的編譯和串連
C語言中並沒有重載和類這些特性,故並不像C++那樣print(int i),會被編譯為_print_int,而是直接編譯為_print等。因此如果直接在C++中調用C的函數會失敗,因為串連是調用C中的print(3)時,它會去找_print_int(3)。因此extern "C"的作用就體現出來了。
3.3、C++中調用C的代碼
假設一個C的標頭檔cHeader.h中包含一個函數print(int i),為了在C++中能夠調用它,必須要加上extern關鍵字。
C++程式調用C函數:http://blog.csdn.net/ustcgy/article/details/5063082
3.4、C中調用C++的代碼
C程式調用C++函數 : http://blog.csdn.net/ustcgy/article/details/5063243
參考連結:http://www.cnblogs.com/skynet/archive/2010/07/10/1774964.html
http://blog.chinaunix.net/uid-24118190-id-2985318.html
C和C++相互調用