c與c++之間的相互調(diào)用及函數(shù)區(qū)別示例詳解
引言
最近項(xiàng)目需要使用google test(以下簡(jiǎn)稱(chēng)為gtest)作為單元測(cè)試框架,但是項(xiàng)目本身過(guò)于龐大,main函數(shù)無(wú)從找起,需要將gtest框架編譯成靜態(tài)庫(kù)使用。因?yàn)轫?xiàng)目本身是通過(guò)純c語(yǔ)言編寫(xiě),而gtest則是一個(gè)c++編寫(xiě)的測(cè)試框架,其中必然涉及c與c++之間的相互調(diào)用。
注意,本文的前提是,c代碼采用gcc等c語(yǔ)言編譯器編譯c代碼,采用g++等c++編譯器編譯c++代碼,如果c和c++代碼統(tǒng)一使用g++編譯,大部分情況是可以實(shí)現(xiàn)兩者代碼相互調(diào)用的。以下為踩坑過(guò)程的總結(jié)o_O||。
c與c++的函數(shù)區(qū)別
要了解兩者之間如何實(shí)現(xiàn)相互調(diào)用,必須先了解c與c++之間的函數(shù)有什么不同。
c++作為c語(yǔ)言的升級(jí)版,兩者必然有很多不同之處。其中有一個(gè)重大不同點(diǎn)就是,c++支持函數(shù)重載,而c語(yǔ)言不支持。為了使函數(shù)支持重載,c++在c語(yǔ)言的基礎(chǔ)上,將函數(shù)名添加上返回值和參數(shù)的類(lèi)型信息。
例如,int add(int, int)
這個(gè)函數(shù),通過(guò)c++編譯器編譯后,可能呈現(xiàn)的函數(shù)名為int int_add_int_int(int, int)
(注:此處為大概地說(shuō)明c++是如何將返回值和參數(shù)信息添加到函數(shù)名中的,實(shí)際中編譯器不一定是這樣實(shí)現(xiàn)的)。
從以上說(shuō)明可以得出,由于c++對(duì)函數(shù)重載的支持,使得編譯后的函數(shù)符號(hào)與c語(yǔ)言的不一致,即使是在兩者函數(shù)名相同的前提下。
extern "C"的作用
那么,c與c++是不能相互調(diào)用了嗎?答案是否定的,因?yàn)榇嬖谥?code>extern "C"這個(gè)關(guān)鍵字可以使語(yǔ)句可以按照類(lèi)C的編譯和連接規(guī)約來(lái)編譯和連接,而不是C++的編譯的連接規(guī)約。這樣在類(lèi)C的代碼中就可以調(diào)用C++的函數(shù)or變量等。
注意:extern "C"
指令中的"C",表示的一種編譯和連接規(guī)約,而不是一種語(yǔ)言。"C"表示符合C語(yǔ)言的編譯和連接規(guī)約的任何語(yǔ)言,如Fortran、assembler等。
還有要說(shuō)明的是,extern "C"
指令僅指定編譯和連接規(guī)約,但不影響語(yǔ)義。例如在函數(shù)聲明中,指定了extern "C"
,仍然要遵守C++的類(lèi)型檢測(cè)、參數(shù)轉(zhuǎn)換規(guī)則。
c++中調(diào)用c代碼
對(duì)于c++,由于c++的編譯器對(duì)c語(yǔ)言兼容,因此在c++中調(diào)用c語(yǔ)言編寫(xiě)的函數(shù),只需要在函數(shù)聲明前面加上關(guān)鍵字extern "C"
,表示采用類(lèi)c語(yǔ)言的方式解析函數(shù)符號(hào)。例子如下:
// add.h #ifdef __ADD_H__ #define __ADD_H__ extern "C" int add(int a, int b); #endif // add.c int add(int a, int b) { return a + b; } // main.cc #include <iostream> #include "add.h" using namespace std; int main() { cout << "1 + 1 = " << add(1, 1) << endl; }
在例子中,main.cc為c++代碼,add.c為c語(yǔ)言代碼,當(dāng)c++編譯器識(shí)別到extern "C"
`關(guān)鍵字時(shí),會(huì)去尋找add函數(shù)的實(shí)現(xiàn)而不是尋找類(lèi)似int_add_int_int這樣帶參數(shù)信息的函數(shù)實(shí)現(xiàn)。
c語(yǔ)言調(diào)用c++代碼
c語(yǔ)言調(diào)用c++代碼卻并不容易,原因是c語(yǔ)言并不兼容c++。就算c語(yǔ)言可以調(diào)用c++,也會(huì)因?yàn)闊o(wú)法識(shí)別c++新定義的符號(hào)而編譯報(bào)錯(cuò)。因此,為了實(shí)現(xiàn)c語(yǔ)言調(diào)用c++函數(shù),必須實(shí)現(xiàn)以下兩個(gè)步驟:1. 將c++相關(guān)函數(shù)封裝為靜態(tài)庫(kù)或動(dòng)態(tài)庫(kù)(因?yàn)檎{(diào)用庫(kù)函數(shù)時(shí)編譯器并不知道里面執(zhí)行的是什么語(yǔ)言);2. 對(duì)外提供遵循類(lèi)c語(yǔ)言規(guī)約的接口函數(shù)。例子如下所示:
// printNum.h #ifdef __PRINTNUM_H__ #define __PRINTNUM_H__ extern "C" void printNum(int a); #endif // printNum.cc #include <iostream> #include "printNum.h" using namespace std; void printNum(int a) { cout << << "num is " << a << endl; } // main.c extern void printNum(int a); printNum(5);
通過(guò)將cout函數(shù)封裝為類(lèi)c語(yǔ)言規(guī)約的接口函數(shù),使得main.c中可以成功調(diào)用c++函數(shù)printNum。值得注意的是,main.c不可以直接引入printNum.h,因?yàn)閏語(yǔ)言不能識(shí)別extern "C"
關(guān)鍵字??梢岳胏++預(yù)定義宏實(shí)現(xiàn)頭文件的改寫(xiě):
#ifdef __PRINTNUM_H__ #define __PRINTNUM_H__ #ifdef __cplusplus extern "C" { #endif void printNum(int a); #ifdef __cplusplus } #endif #endif
小結(jié)
小結(jié)如下:
- c語(yǔ)言與c++的相互調(diào)用可以通過(guò)
extern "C"
關(guān)鍵字實(shí)現(xiàn) - c++中調(diào)用c代碼,只須在c++中為c代碼函數(shù)聲明之前加上
extern "C"
- c語(yǔ)言調(diào)用c++代碼,則需要將c++代碼編譯成靜態(tài)庫(kù)或動(dòng)態(tài)庫(kù),然后對(duì)外提供用
extern "C"
聲明的類(lèi)c封裝函數(shù)
以上就是c與c++之間的相互調(diào)用及函數(shù)區(qū)別示例詳解的詳細(xì)內(nèi)容,更多關(guān)于c c++相互調(diào)用的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C 語(yǔ)言編寫(xiě)一個(gè)計(jì)算器界面(可視化界面和多功能)
今天給大家分享一個(gè)計(jì)算器功能,主要功能有加法減法乘除法求余功能,用戶(hù)可以在主菜單選擇需要計(jì)算的功能,接下來(lái)根據(jù)用戶(hù)輸入的數(shù)字進(jìn)行計(jì)算輸出結(jié)果,喜歡的朋友拿去用吧2021-06-06Prim(普里姆)算法求最小生成樹(shù)的思想及C語(yǔ)言實(shí)例講解
Prim算法能夠在帶權(quán)的圖中搜索出最小生成樹(shù),這也是各大ACM和面試及考研題目中的熱點(diǎn),下面我們就來(lái)詳細(xì)看一下Prim(普里姆)算法求最小生成樹(shù)的思想及C語(yǔ)言實(shí)例講解2016-06-06C語(yǔ)言 詳細(xì)解析時(shí)間復(fù)雜度與空間復(fù)雜度
算法復(fù)雜度分為時(shí)間復(fù)雜度和空間復(fù)雜度。其作用: 時(shí)間復(fù)雜度是度量算法執(zhí)行的時(shí)間長(zhǎng)短;而空間復(fù)雜度是度量算法所需存儲(chǔ)空間的大小2022-04-04Cocos2d-x UI開(kāi)發(fā)之CCControlPotentiometer控件類(lèi)使用實(shí)例
這篇文章主要介紹了Cocos2d-x UI開(kāi)發(fā)之CCControlPotentiometer控件類(lèi)使用實(shí)例,本文代碼中包含注釋來(lái)講解CCControlPotentiometer控件類(lèi)的使用,需要的朋友可以參考下2014-09-09Qt實(shí)現(xiàn)http服務(wù)的示例代碼
這篇文章將為大家詳細(xì)講解有關(guān)Qt如何實(shí)現(xiàn)http服務(wù),小編覺(jué)得挺實(shí)用的,因此分享給大家做個(gè)參考,希望大家閱讀完這篇文章后可以有所收獲2023-04-04C++實(shí)現(xiàn)將s16le的音頻流轉(zhuǎn)換為float類(lèi)型
這篇文章主要為大家詳細(xì)介紹了如何利用C++實(shí)現(xiàn)將s16le的音頻流轉(zhuǎn)換為float類(lèi)型,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起了解一下2023-04-04C語(yǔ)言實(shí)現(xiàn)冒泡排序算法的示例詳解
這篇文章主要介紹了C語(yǔ)言如何實(shí)現(xiàn)冒泡排序算法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-04-04C語(yǔ)言詳細(xì)講解qsort函數(shù)的使用
排序方法有很多種:選擇排序,冒泡排序,歸并排序,快速排序等??疵侄贾揽焖倥判蚴悄壳肮J(rèn)的一種比較好的排序算法。因?yàn)樗俣群芸?,所以系統(tǒng)也在庫(kù)里實(shí)現(xiàn)這個(gè)算法,便于我們的使用。這就是qsort函數(shù)2022-04-04