0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

C与C++如何互相调用

3D视觉工坊 来源:3D视觉工坊 2023-01-15 14:50 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

在项目开发过程中,我们底层代码经常用C来实现,而上层应用大都会用C++实现,这样我们就涉及到了CC++相互调用的情况了。那么,C/C++如何实现相互调用呢?

1、为什么会有差异?

1)编译方式不同C文件常采用gcc编译,而Cpp文件常采用g++来编译2)C++支持函数重载:由于这一特性,C++C中的同一个函数,经过编译后,生成的函数名称是不同的。 这样就导致了CC++之间不能直接进行调用,要解决这一问题,就得靠extern "C"来辅助了。

2、extern "C"

·externextern关键字我们并不陌生,它是编程语言中的一种属性,用来表示变量,函数等类型的作用范围。
我们经常在.c源文件中定义变量或者实现函数,在.h头文件中使用extern关键字进行声明,方便其他文件调用。
·"C"编程语言种类繁多,不同语言有不同的编译规则,如果想要互相调用,必须告诉编译器以什么规则去编译文件,这样才能正常调用。其主要作用是:把“C”当作一个标志位,告诉编译器,下面代码以C的方式编译!
了解其中原理后,我们来实操一下!

3、C++调用C

我们创建3个文件,分别为main.cppcal.ccal.h

e8415ed6-9431-11ed-bfe3-dac502259ad0.jpg

我们分别使用gccg++单独编译文件,编译出cal.omain.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.omain.o的符号表,看看同一个函数embedded_art不同编译方式之后的差别。
		

e8531202-9431-11ed-bfe3-dac502259ad0.jpg

可以看到,g++编译之后,对函数名称进行了加工,按照自身的编译规则,最终生成了一个新的函数名,所以我们如果直接调用cal.c中的embedded_art肯定是不行的。

正确方式

使用extern "C"来使g++编译器用C的方式编译。main.cpp文件中,我们引入cal.h的位置,添加extern "C"

	extern "C" { #include "cal.h" }再次进行编译,即可!
		

e86156b4-9431-11ed-bfe3-dac502259ad0.jpg

可以看到符号表中,该函数名称正常,然后我们将中间文件链接起来,执行,输出正确结果!

	# 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.ccal.cppcal.h

e87635a2-9431-11ed-bfe3-dac502259ad0.jpg

我们分别使用gccg++单独编译文件,编译出cal.omain.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.omain.o的符号表,看看同一个函数embedded_art不同编译方式之后的差别。
		

e884e37c-9431-11ed-bfe3-dac502259ad0.jpg

同样,不同的编译器处理方式不同,函数名称依旧不同!同样,需要加入extern "C"来告诉编译器按C的方式编译。我们在cal.h的声明部分添加,然后重新编译!

	extern "C" { extern void embedded_art(void); }
		

e8926448-9431-11ed-bfe3-dac502259ad0.jpg

可以看到符号表中,该函数名称正常,然后我们将中间文件链接起来。

e8a24b1a-9431-11ed-bfe3-dac502259ad0.jpg

这个时候,会出现报错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

    文章

    4406

    浏览量

    66838
  • C++
    C++
    +关注

    关注

    22

    文章

    2122

    浏览量

    76712
  • 编译器
    +关注

    关注

    1

    文章

    1669

    浏览量

    51082
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    C/C++条件编译

    条件编译是一种在编译时根据条件选择性地包含或排除部分代码的处理方法。在 C/C++ 中,条件编译使用预处理指令 #ifdef、#endif、#else 和 #elif 来实现。常用的条件编译指令有
    发表于 12-05 06:21

    C++程序异常的处理机制

    1、什么是异常处理? 有经验的朋友应该知道,在正常的CC++编程过程中难免会碰到程序不按照原本设计运行的情况。 最常见的有除法分母为零,数组越界,内存分配失效、打开相应文件失败等等。 一个程序
    发表于 12-02 07:12

    C/C++代码静态测试工具Perforce QAC 2025.3的新特性

     Perforce Validate 中 QAC 项目的相对/根路径的支持。C++ 分析也得到了增强,增加了用于检测 C++ 并发问题的新检查,并改进了实体名称和实
    的头像 发表于 10-13 18:11 345次阅读
    <b class='flag-5'>C</b>/<b class='flag-5'>C++</b>代码静态测试工具Perforce QAC 2025.3的新特性

    技能+1!如何在树莓派上使用C++控制GPIO?

    在使用树莓派时,你会发现Python和Scratch是许多任务(包括GPIO编程)中最常用的编程语言。但你知道吗,你也可以使用C++进行GPIO编程,而且这样做还有不少好处。借助WiringPi
    的头像 发表于 08-06 15:33 3573次阅读
    技能+1!如何在树莓派上使用<b class='flag-5'>C++</b>控制GPIO?

    C++ 与 Python:树莓派上哪种语言更优?

    Python是树莓派上的首选编程语言,我们的大部分教程都使用它。然而,C++在物联网项目中同样广受欢迎且功能强大。那么,在树莓派项目中选择哪种语言更合适呢?Python因其简洁性、丰富的库和资源而被
    的头像 发表于 07-24 15:32 642次阅读
    <b class='flag-5'>C++</b> 与 Python:树莓派上哪种语言更优?

    Perforce QAC产品简介:面向C/C++的静态代码分析工具(已通过SO 26262认证)

    Perforce QAC专为C/C++开发者打造,支持多种编码规范、功能安全标准(ISO 26262)等,广泛用于汽车、医疗、嵌入式开发领域,可帮助快速识别关键缺陷、提升代码质量、实现合规交付。
    的头像 发表于 07-10 15:57 846次阅读
    Perforce QAC产品简介:面向<b class='flag-5'>C</b>/<b class='flag-5'>C++</b>的静态代码分析工具(已通过SO 26262认证)

    主流的 MCU 开发语言为什么是 C 而不是 C++

    在单片机的地界儿里,C语言稳坐中军帐,C++想分杯羹?难喽。咱电子工程师天天跟那针尖大的内存空间较劲,C++那些花里胡哨的玩意儿,在这儿真玩不转。先说内存这道坎儿。您当stm32f4的256kRAM
    的头像 发表于 05-21 10:33 778次阅读
    主流的 MCU 开发语言为什么是 <b class='flag-5'>C</b> 而不是 <b class='flag-5'>C++</b>?

    源代码加密、源代码防泄漏c/c++与git服务器开发环境

    源代码加密对于很多研发性单位来说是至关重要的,当然每家企业的业务需求不同所用的开发环境及开发语言也不尽相同,今天主要来讲一下c++及git开发环境的源代码防泄密保护方案。企业源代码泄密场景一、在很多
    的头像 发表于 02-12 15:26 876次阅读
    源代码加密、源代码防泄漏<b class='flag-5'>c</b>/<b class='flag-5'>c++</b>与git服务器开发环境

    基于OpenHarmony标准系统的C++公共基础类库案例:ThreadPoll

    1、程序简介该程序是基于OpenHarmony标准系统的C++公共基础类库的线程池处理:ThreadPoll。本案例完成如下工作:创建1个线程池,设置该线程池内部有1024个线程空间。启动5个线程
    的头像 发表于 02-10 18:09 600次阅读
    基于OpenHarmony标准系统的<b class='flag-5'>C++</b>公共基础类库案例:ThreadPoll

    Spire.XLS for C++组件说明

    Spire.XLS for C++ 是一款专业的 C++ Excel 组件,可以用在各种 C++ 框架和应用程序中。Spire.XLS for C++ 提供了一个对象模型 Excel
    的头像 发表于 01-14 09:40 1297次阅读
    Spire.XLS for <b class='flag-5'>C++</b>组件说明

    EE-128:C语言中的DSP:从C调用汇编类成员函数

    电子发烧友网站提供《EE-128:C语言中的DSP:从C调用汇编类成员函数.pdf》资料免费下载
    发表于 01-07 13:48 0次下载
    EE-128:<b class='flag-5'>C</b>语言中的DSP:从<b class='flag-5'>C</b><b class='flag-5'>调用</b>汇编类成员函数

    EE-112:模拟C++中的类实现

    电子发烧友网站提供《EE-112:模拟C++中的类实现.pdf》资料免费下载
    发表于 01-03 15:15 0次下载
    EE-112:模拟<b class='flag-5'>C++</b>中的类实现

    AKI跨语言调用库神助攻C/C++代码迁移至HarmonyOS NEXT

    /C++代码快速迁移至HarmonyOS NEXT。凭借卓越的兼容性,AKI已成为厂商与开发者打造鸿蒙原生应用过程中广泛使用的跨语言调用解决方案。 AKI是一款专为鸿蒙原生开发设计的FFI(外部函数接口
    发表于 01-02 17:08

    HighTec C/C++编译器套件全面支持芯来RISC-V IP

    德国萨尔布吕肯,2024年12月5日——世界领先的汽车C/C++编译器解决方案提供商HighTec EDV Systeme GmbH宣布全面支持芯来科技的RISC-V IP。HighTec编译器
    的头像 发表于 12-23 09:04 2001次阅读
    HighTec <b class='flag-5'>C</b>/<b class='flag-5'>C++</b>编译器套件全面支持芯来RISC-V IP

    运动控制卡周期上报实时数据IO状态之C++

    使用C++进行运动控制卡的周期上报功能实现
    的头像 发表于 12-17 13:59 1528次阅读
    运动控制卡周期上报实时数据IO状态之<b class='flag-5'>C++</b>篇