C與C 混合程式設計需要注意的問題

2022-01-09 22:20:02 字數 1983 閱讀 6720

這篇文章講解的知識點很「小」,但是在c和c++的混合程式設計中非常重要。

因為我們在寫應用程式時,經常利用到第三方的程式。

如果我們的**用c,但是第三方**是c++;

或者我們的**用c++,而第三方的**是c,

那麼在整合的時候就需要仔細一點了。

一、c呼叫c++中的函式

1. 被呼叫c++**中的標頭檔案(callee.h)

2. 被呼叫c++**中的原始檔(callee.cpp)

3. 被呼叫c++**編譯成目標檔案(callee.o)

知識點:

(1)關於 __cplusplus

編譯器使用g++,所有的c++編譯器中都會定義巨集:__cplusplus,因此在編譯callee.h的時候,會把函式宣告包裹在extern "c" 中。

(2)關於 extern "c"

c和c++編譯器,在編譯乙個函式的時候,編譯策略是不同的。c++會對函式的名稱進行改寫(而且每個c++編譯器對於名字改寫的規則也是不一樣的,甚至同乙個編譯器的不同版本的名字改寫規則也不一樣,因此,使用c++時最好用相同的編譯器版本對專案中的所有模組進行編譯。補充:改寫的目的是為了實現c++語言中的函式過載)。

在callee.h中,把函式 cpp_hello 放在 extern "c" 中,意思就是告訴編譯器g++: 這個函式是需要被c呼叫的,請不要對這個函式進行名字改寫。

可以通過 nm 指令檢視一下目標檔案callee.o中的符號:

我們可以多做乙個測試:把extern "c"去掉之後,看一下這個函式如何被g++改寫了名字:

4. 主呼叫c**中的原始檔(caller.c)

5. 編譯主呼叫c檔案,得到可執行檔案

知識點:

(1)caller.c在 include 「callee.h" 時,gcc編譯器中沒有定義 __cplusplus 巨集,所以 callee.h 中就相當於只有一句話:void cpp_helo();

(2)在呼叫 cpp_hello()函式時,雖然這個函式是用g++編譯的,但是由於使用了 extern "c",所以名字沒有被編譯器g++改寫,也就是說,在callee.o目標檔案中,函式的名字就是 "cpp_hello",所以可以順利的被c**呼叫到。

二、c++呼叫c中的函式

1. 被呼叫c**中的標頭檔案(callee.h)

2. 被呼叫c**中的原始檔(callee.c)

3. 被呼叫c**編譯成目標檔案(callee.o)

知識點:

編譯器使用gcc,其中沒有定義巨集:__cplusplus,因此在編譯callee.h的時候,相當於只有乙個函式宣告。因此函式c_hello在被編譯到callee.o目標檔案中時,沒有被改名。

4. 主呼叫c++**原始檔(caller.cpp)

5. 編譯主呼叫c++檔案,得到可執行檔案

知識點:

g++在編譯callee.h時,由於g++中定義了__cplusplus巨集,因此它在呼叫函式 c_hello時,就會按照c的方式去呼叫(也就是沒有名字改寫),所以就能順利的在callee.o中查詢到這個函式。

三、總結

1. 在c++**的函式宣告時,如果**會被c程式呼叫,一定要加上 extern "c"。

2. 在c**的函式宣告時,如果**會被c++程式呼叫,也要加上extern "c"。

3. 在用c++程式設計時,最好各模組統一使用相同的編譯器,包括版本最好也相同。

不知道這篇博文對你有沒有幫助呢?

c與c 混合程式設計

在純c的系統中使用c 的類出現了編譯錯誤!程式 begin mymain.c include thesocket.h void main int argc,char argv end mymain.c begin thesocket.h class thesocket end thesocket.h...

c與c 混合程式設計

1.引言 c 語言的建立初衷是 a better c 但是這並不意味著c 中類似 c語言的全域性 變數和函式所採用的編譯和連線方式與c語言完全相同。作為一種欲與c相容的語言,c 保留了一部分過程式語言的特點 被世人稱為 不徹底地物件導向 因而它可以定義不屬於任何類的全域性變數和函式。但是,c 畢竟是...

C與C 混合程式設計

c 是在 c 語言的基礎上發展起來的。在某種程度上,我們可將 c 看做 c 的一種擴充套件。在本質上,二者的資料型別和函式呼叫慣例都是一致的,因此 c 與 c 混合編譯也是很自然的事情。二者的區別僅在於編譯後函式的名字不同 c 簡單地使用函式名而不考慮引數的個數或型別,而 c 編譯後的函式名則總是將...