在項目開發過程中,我們底層代碼經常用C
來實現,而上層應用大都會用C++
實現,這樣我們就涉及到了C
和C++
相互調用的情況了。那么,C/C++
如何實現相互調用呢?
1、為什么會有差異?
1)編譯方式不同:C
文件常采用gcc
編譯,而Cpp
文件常采用g++
來編譯2)C++
支持函數重載:由于這一特性,C++
和C
中的同一個函數,經過編譯后,生成的函數名稱是不同的。
這樣就導致了C
與C++
之間不能直接進行調用,要解決這一問題,就得靠extern "C"
來輔助了。2、extern "C"
·externextern
關鍵字我們并不陌生,它是編程語言中的一種屬性,用來表示變量,函數等類型的作用范圍。
我們經常在·"C"編程語言種類繁多,不同語言有不同的編譯規則,如果想要互相調用,必須告訴編譯器以什么規則去編譯文件,這樣才能正常調用。其主要作用是:把.c
源文件中定義變量或者實現函數,在.h
頭文件中使用extern
關鍵字進行聲明,方便其他文件調用。
“C”
當作一個標志位,告訴編譯器,下面代碼以C
的方式編譯!了解其中原理后,我們來實操一下!
3、C++調用C
我們創建3個文件,分別為main.cpp
、cal.c
、cal.h
。
我們分別使用
gcc
和g++
單獨編譯文件,編譯出cal.o
和main.o
兩個中間文件,很簡單,定義了一個embedded_art
的函數。# dong @ ubuntu in ~/WorkSpace/Donge_Programs/Unix_Programming_Learning/c_c++_call_test on git:main x [1532] $ ls cal.c cal.h main.cpp # dong @ ubuntu in ~/WorkSpace/Donge_Programs/Unix_Programming_Learning/c_c++_call_test on git:main x [1543] $ gcc -c cal.c # dong @ ubuntu in ~/WorkSpace/Donge_Programs/Unix_Programming_Learning/c_c++_call_test on git:main x [1549] $ g++ -c main.cpp # dong @ ubuntu in ~/WorkSpace/Donge_Programs/Unix_Programming_Learning/c_c++_call_test on git:main x [1555] $ ls cal.c cal.h cal.o main.cpp main.o
下面看一下編譯之后的中間文件cal.o
和main.o
的符號表,看看同一個函數embedded_art
不同編譯方式之后的差別。
可以看到,
g++
編譯之后,對函數名稱進行了加工,按照自身的編譯規則,最終生成了一個新的函數名,所以我們如果直接調用cal.c
中的embedded_art
肯定是不行的。正確方式
使用extern "C"
來使g++
編譯器用C
的方式編譯。在main.cpp
文件中,我們引入cal.h
的位置,添加extern "C"
extern "C" { #include "cal.h" }
再次進行編譯,即可!
可以看到符號表中,該函數名稱正常,然后我們將中間文件鏈接起來,執行,輸出正確結果!
# dong @ ubuntu in ~/WorkSpace/Donge_Programs/Unix_Programming_Learning/c_c++_call_test on git:main x [1636] $ g++ main.o cal.o # dong @ ubuntu in ~/WorkSpace/Donge_Programs/Unix_Programming_Learning/c_c++_call_test on git:main x [1654] $ ls a.out cal.c cal.h cal.o main.cpp main.o # dong @ ubuntu in ~/WorkSpace/Donge_Programs/Unix_Programming_Learning/c_c++_call_test on git:main x [1657] $ ./a.out main entry 嵌入式藝術
4、C調用C++
我們創建3個文件,分別為main.c
、cal.cpp
、cal.h
。
我們分別使用
gcc
和g++
單獨編譯文件,編譯出cal.o
和main.o
兩個中間文件,很簡單,同樣定義了一個embedded_art
的函數。# dong @ ubuntu in ~/WorkSpace/Donge_Programs/Unix_Programming_Learning/c_c++_call_test/c_call_c++ on git:main x [1645] $ g++ -c cal.cpp # dong @ ubuntu in ~/WorkSpace/Donge_Programs/Unix_Programming_Learning/c_c++_call_test/c_call_c++ on git:main x [1652] $ gcc -c main.c # dong @ ubuntu in ~/WorkSpace/Donge_Programs/Unix_Programming_Learning/c_c++_call_test/c_call_c++ on git:main x [1656] $ ls cal.cpp cal.h cal.o main.c main.o
下面看一下編譯之后的中間文件cal.o
和main.o
的符號表,看看同一個函數embedded_art
不同編譯方式之后的差別。
同樣,不同的編譯器處理方式不同,函數名稱依舊不同!同樣,需要加入
extern "C"
來告訴編譯器按C
的方式編譯。我們在cal.h
的聲明部分添加,然后重新編譯!extern "C" { extern void embedded_art(void); }
可以看到符號表中,該函數名稱正常,然后我們將中間文件鏈接起來。
這個時候,會出現報錯
extern "C"
,這是什么情況?在main.c
文件中,引入了c++
的頭文件cal.h
,因為"C"
在C++
編譯的時候才能識別,C
語言中并沒有這個關鍵字。所以,我們需要在g++
編譯的時候去加入extern "C"
,而gcc
編譯的時候跳過,這個時候就要提到c++
編譯時候的特定宏__cplusplus
了,相當于一個閥門了。我們修改cal.h
文件:#ifdef __cplusplus extern "C" { #endif extern void embedded_art(void); #ifdef __cplusplus } #endif
這樣就確保了,c++
編譯embedded_art
函數的時候,采用C
語法編譯,而gcc
編譯的時候,不作處理。再次鏈接,執行!# dong @ ubuntu in ~/WorkSpace/Donge_Programs/Unix_Programming_Learning/c_c++_call_test/c_call_c++ on git:main x [1606] C:1 $ gcc -no-pie cal.o main.o -o main # dong @ ubuntu in ~/WorkSpace/Donge_Programs/Unix_Programming_Learning/c_c++_call_test/c_call_c++ on git:main x [1646] $ ls cal.cpp cal.h cal.o main main.c main.o # dong @ ubuntu in ~/WorkSpace/Donge_Programs/Unix_Programming_Learning/c_c++_call_test/c_call_c++ on git:main x [1601] $ ./main main entry 嵌入式藝術
5、總結
C/C++
之間的相互調用,歸根到底就是:不同的語言有不同的編譯規則,要想實現通用,就必須告訴編譯器,按照目標語言的規則進行編譯!
審核編輯 :李倩
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。
舉報投訴
-
函數
+關注
關注
3文章
4346瀏覽量
62979 -
C++
+關注
關注
22文章
2114瀏覽量
73860 -
編譯器
+關注
關注
1文章
1642瀏覽量
49292
發布評論請先 登錄
相關推薦
Spire.XLS for C++組件說明
Spire.XLS for C++ 是一款專業的 C++ Excel 組件,可以用在各種 C++ 框架和應用程序中。Spire.XLS for C++ 提供了一個對象模型 Excel
AKI跨語言調用庫神助攻C/C++代碼遷移至HarmonyOS NEXT
/C++代碼快速遷移至HarmonyOS NEXT。憑借卓越的兼容性,AKI已成為廠商與開發者打造鴻蒙原生應用過程中廣泛使用的跨語言調用解決方案。
AKI是一款專為鴻蒙原生開發設計的FFI(外部函數接口
發表于 01-02 17:08
同樣是函數,在C和C++中有什么區別
同樣是函數,在 C 和 C++ 中有什么區別? 第一個返回值。 C語言的函數可以不寫返回值類型,編譯器會默認為返回 int。 但是 C++ 的函數,除了構造和析構這兩個特殊的函數,必須
TMS320C28x優化C/C++編譯器v22.6.0.LTS
電子發燒友網站提供《TMS320C28x優化C/C++編譯器v22.6.0.LTS.pdf》資料免費下載
發表于 10-31 10:10
?0次下載
基于OpenHarmony標準系統的C++公共基礎類庫案例:SafeMap
1、程序簡介該程序是基于OpenHarmony的C++公共基礎類庫的安全關聯容器:SafeMap。OpenHarmony提供了一個線程安全的map實現。SafeMap在STLmap基礎上封裝互斥鎖
OpenVINO2024 C++推理使用技巧
很多人都使用OpenVINO新版的C++ 或者Python的SDK,都覺得非常好用,OpenVINO2022之后的版本C++ SDK做了大量的優化與整理,已經是非常貼近開發的使用習慣與推理方式。與OpenCV的Mat對象對接方式更是幾乎無縫對接,非常的方便好用。
C++中實現類似instanceof的方法
C++有多態與繼承,但是很多人開始學習C++,有時候會面臨一個常見問題,就是如何向下轉型,特別是不知道具體類型的時候,這個時候就希望C++ 可以向Java或者Python中有instanceof這個
使用 MISRA C++:2023? 避免基于范圍的 for 循環中的錯誤
在前兩篇博客中,我們?向您介紹了新的 MISRA C++ 標準?和?C++ 的歷史?。在這篇博客中,我們將仔細研究以 C++ 中?for?循環為中心的特定規則。
評論