這篇文章講解的知識點很“小”,但是在C和C++的混合編程中非常重要。因為我們在寫應用程序時,經常利用到第三方的程序。如果我們的代碼用C,但是第三方代碼是C++;或者我們的代碼用C++,而第三方的代碼是C,那么在整合的時候就需要仔細一點了。
一、C調用C++中的函數
- 被調用C++代碼中的頭文件(callee.h)
- 被調用C++代碼中的源文件(callee.cpp)
- 被調用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++改寫了名字:
- 主調用C代碼中的源文件(caller.c)
- 編譯主調用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中的函數
- 被調用C代碼中的頭文件(callee.h)
- 被調用C代碼中的源文件(callee.c)
- 被調用C代碼編譯成目標文件(callee.o)
知識點:
編譯器使用gcc,其中沒有定義宏:__cplusplus,因此在編譯callee.h的時候,相當于只有一個函數聲明。因此函數c_hello在被編譯到callee.o目標文件中時,沒有被改名。
- 主調用C++代碼源文件(caller.cpp)
- 編譯主調用C++文件,得到可執行文件
知識點:
g++在編譯callee.h時,由于g++中定義了__cplusplus宏,因此它在調用函數 c_hello時,就會按照C的方式去調用(也就是沒有名字改寫),所以就能順利的在callee.o中查找到這個函數。
三、總結
- 在C++代碼的函數聲明時,如果代碼會被C程序調用,一定要加上 extern "C"。
- 在C代碼的函數聲明時,如果代碼會被C++程序調用,也要加上extern "C"。
- 在用C++編程時,最好各模塊統一使用相同的編譯器,包括版本最好也相同。
-
C++
+關注
關注
22文章
2116瀏覽量
74486 -
代碼
+關注
關注
30文章
4868瀏覽量
69900 -
應用程序
+關注
關注
38文章
3310瀏覽量
58443
發布評論請先 登錄
相關推薦
STM32CubeMX如何在*.c源文件中使用c++特性?
Matlab與C/C++ 混合編程技術總結的太棒了
STM32c/c++混合編程
ARM匯編與C混合編程的相關資料分享
RT-Thread如何實現C\C++的混合編譯?要在哪里修改GCC的鏈接腳本?
Matlab與C/C++混合編程接口及應用方法解析
淺談關于DSP6000中C/C++語言和匯編語言的混合編程的方法
MATLAB和C++混合編程入門資料說明

海思AI芯片(Hi3519A/3559A)方案學習(二十一)extern "C"和C/C++混合編程

評論