在项目开发过程中,我们底层代码经常用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源文件中定义变量或者实现函数,在.h头文件中使用extern关键字进行声明,方便其他文件调用。 ·c编程语言种类繁多,不同语言有不同的编译规则,如果想要互相调用,必须告诉编译器以什么规则去编译文件,这样才能正常调用。其主要作用是:把“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++之间的相互调用,归根到底就是:不同的语言有不同的编译规则,要想实现通用,就必须告诉编译器,按照目标语言的规则进行编译!
数据库select语句的基本用法
《人民日报》关注中国量子算力在移动通信领域的应用
联通公开曝光三起违反党纪企规的典型案例
电工为什么不愿意装漏电保护
贸泽电子再次荣膺TE Connectivity 年度全球卓越服务分销商奖
C与C++如何互相调用
英飞凌推出低成本半瓦LED驱动器系列
华为何刚:预计nova下月累计出货超一亿台
中国无人机助国际快运公司实现全自动递送 可减少80%成本
仙童半导体公司的故事
分析小型QFN封装的更高效第二代WiMAX功率放大器设计
MP3节能妙招
企业网站建设容易维护难?华为云服务器保障长期高效运营
电动车RFID防盗应用技术说明
ASJ系列剩余电流继电器在施工场地中的应用
中车长客正研制超导电动直线马达高速磁浮列车
星纵智能灯光控制器,单机8路开关,轻松实现灯光远程批量管理!
安富利:6G网络能终结城市拥堵吗?
电感安规收费服务上线——色码电感定制Q
城市河道水质监测无人机高光谱技术应用研究-莱森光学