C與C 之間的呼叫

2021-07-11 22:34:22 字數 1649 閱讀 3037

注意這裡的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++方式編譯。

例如: // c++ code:

class c

;然後,你就可以這樣呼叫 c::f():

//c code

double call_c_f(struct c* p, int i);//宣告

void ccc(struct c* p, int i)

問題:引數struct c* p從**來,即怎麼在c中定義c++物件,其實上面只是說了思想,真實的c中使用c++類需要把原來的類都封裝一下,參看下面的文章

而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

其中__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"

C與C 之間相互呼叫

c與c 之間相互呼叫 1 匯出c函式以用於c或c 的專案 如果使用c語言編寫的dll,希望從中匯出函式給c或c 的模組訪問,則應使用 cplusplus 預處理器巨集確定正在編譯的語言。如果是從c 語言模組使用,則用c鏈結宣告這些函式。如果使用此技術並為dll提供標頭檔案,則這些函式可以原封不動地由...

C與C 之間相互呼叫

1 匯出c函式以用於c或c 的專案 如果使用c語言編寫的dll,希望從中匯出函式給c或c 的模組訪問,則應使用 cplusplus 預處理器巨集確定正在編譯的語言。如果是從c 語言模組使用,則用c鏈結宣告這些函式。如果使用此技術並為dll提供標頭檔案,則這些函式可以原封不動地由c和c 模組使用。以下...

C與C 之間相互呼叫

1 匯出c函式以用於c或c 的專案 如果使用c語言編寫的dll,希望從中匯出函式給c或c 的模組訪問,則應使用 cplusplus 預處理器巨集確定正在編譯的語言。如果是從c 語言模組使用,則用c鏈結宣告這些函式。如果使用此技術並為dll提供標頭檔案,則這些函式可以原封不動地由c和c 模組使用。以下...