如何让一个 C 语言项目调用另一个 C++ 项目中某些类所提供的接口?

2023-05-16

目前問題是這樣的:有兩個項目 一個項目是用 C++ 寫的 裏面提供了一個輸入輸出接口 後來從外面弄來了另外一個項目 用 C 寫的 現在需要將 C 項目中所使用的原有接口替換為使用我們的 C++ 項目中提供的接口 求問能夠實現否?

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

1、为什么会有差异?

  • 编译方式不同C文件常采用gcc编译,而Cpp文件常采用g++来编译
  • C++支持函数重载:由于这一特性,C++C中的同一个函数,经过编译后,生成的函数名称是不同的。

这样就导致了CC++之间不能直接进行调用,要解决这一问题,就得靠extern "C"来辅助了。

2、extern “C”

  • extern

extern关键字我们并不陌生,它是编程语言中的一种属性,用来表示变量,函数等类型的作用范围。

我们经常在.c源文件中定义变量或者实现函数,在.h头文件中使用extern关键字进行声明,方便其他文件调用。

  • “C”

编程语言种类繁多,不同语言有不同的编译规则,如果想要互相调用,必须告诉编译器以什么规则去编译文件,这样才能正常调用。

其主要作用是:把“C”当作一个标志位,告诉编译器,下面代码以C的方式编译!

了解其中原理后,我们来实操一下!

3、C++调用C

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

img

我们分别使用gccg++单独编译文件,编译出cal.omain.o两个中间文件,很简单,定义了一个embedded_art的函数。

# dong @ ubuntu in ~/WorkSpace/Donge_Programs/Unix_Programming_Learning/c_c++_call_test on git:main x [15:57:32] 
$ ls
cal.c  cal.h  main.cpp

# dong @ ubuntu in ~/WorkSpace/Donge_Programs/Unix_Programming_Learning/c_c++_call_test on git:main x [15:57:43] 
$ gcc -c cal.c 

# dong @ ubuntu in ~/WorkSpace/Donge_Programs/Unix_Programming_Learning/c_c++_call_test on git:main x [15:57:49] 
$ g++ -c main.cpp 

# dong @ ubuntu in ~/WorkSpace/Donge_Programs/Unix_Programming_Learning/c_c++_call_test on git:main x [15:57:55] 
$ ls
cal.c  cal.h  cal.o  main.cpp  main.o

下面看一下编译之后的中间文件cal.omain.o的符号表,看看同一个函数embedded_art不同编译方式之后的差别。

img

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

正确方式

使用extern "C"来使g++编译器用C的方式编译。

main.cpp文件中,我们引入cal.h的位置,添加extern "C"

extern "C" {
#include "cal.h"
}

再次进行编译,即可!

img

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

# dong @ ubuntu in ~/WorkSpace/Donge_Programs/Unix_Programming_Learning/c_c++_call_test on git:main x [16:18:36] 
$ g++ main.o cal.o 

# dong @ ubuntu in ~/WorkSpace/Donge_Programs/Unix_Programming_Learning/c_c++_call_test on git:main x [16:19:54] 
$ 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 [16:19:57] 
$ ./a.out 
main entry
嵌入式艺术

4、C调用C++

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

img

我们分别使用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 [16:24:45] 
$ g++ -c cal.cpp   

# dong @ ubuntu in ~/WorkSpace/Donge_Programs/Unix_Programming_Learning/c_c++_call_test/c_call_c++ on git:main x [16:24:52] 
$ gcc -c main.c    

# dong @ ubuntu in ~/WorkSpace/Donge_Programs/Unix_Programming_Learning/c_c++_call_test/c_call_c++ on git:main x [16:24:56] 
$ ls
cal.cpp  cal.h  cal.o  main.c  main.o

下面看一下编译之后的中间文件cal.omain.o的符号表,看看同一个函数embedded_art不同编译方式之后的差别。

img

同样,不同的编译器处理方式不同,函数名称依旧不同!同样,需要加入extern "C"来告诉编译器按C的方式编译。

我们在cal.h的声明部分添加,然后重新编译!

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

img

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

img

这个时候,会出现报错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 [16:45:06] 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 [16:46:46] 
$ 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 [16:49:01] 
$ ./main
main entry
嵌入式艺术

5、总结

C/C++之间的相互调用,归根到底就是:不同的语言有不同的编译规则,要想实现通用,就必须告诉编译器,按照目标语言的规则进行编译!


转载于:如何让一个 C 语言项目调用另一个 C++ 项目中某些类所提供的接口? - 嵌入式艺术的回答 - 知乎
https://www.zhihu.com/question/20107056/answer/2811222653

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何让一个 C 语言项目调用另一个 C++ 项目中某些类所提供的接口? 的相关文章

  • 片内总线在cpu扮演什么角色?他为什么能实现高效,不同的CPU为什么采用不同的总线协议?

    文章目录 各种新型片上总线维度 xff08 Degree xff09 跳 xff08 Hop xff09 和跳数 xff08 Hop Count xff0c HC xff09 直连拓扑和路由器 Intel的Ring和Mesh 43 总线双R
  • 如何一步一步成为一个技术领域专家

    已剪辑自 https mp weixin qq com s biz 61 Mzg4NjIxODk4Mg 61 61 amp mid 61 2247497216 amp idx 61 1 amp sn 61 12c8b2449baa2c236
  • 电子电气架构设计需要考虑哪些方面?

    当前车辆日益复杂 xff0c 车联网功能在各个细分领域都在不断增加 xff0c 而更强大的智能功能也逐步增加 所有这些高级功能都依赖于线束和控制器才能发挥作用 然而面对日益增加的车辆复杂性和产品开发周期缩短的压力 xff0c 导致汽车制造商
  • 深度解读汽车域控制器

    已剪辑自 https mp weixin qq com s biz 61 Mzg4NjIxODk4Mg 61 61 amp mid 61 2247496089 amp idx 61 1 amp sn 61 db5c08f97342decfa
  • 单片机硬件和软件延时、RTOS相对延时和绝对延时

    已剪辑自 https mp weixin qq com s RPLQn4KO9Aqu1fpfZeOKA 前不久有个读者在问关于延时的问题 xff0c 大概就是问 xff1a 软件延时和硬件延时是啥意思 xff1f 做项目时他俩有什么区别 x
  • 计算机端口的安全知识大全,整的明明白白!

    已剪辑自 https cloud tencent com developer article 1406267 看了网安众安的这篇计算机端口文章 xff0c 你要是学不会你来打我 鲁迅没有说过 端口是计算机的大门 xff0c 计算机的安全应该
  • 自然语言处理概述

    文章目录 本文系书稿选登 2 1 自然语言处理概述2 1 1 什么是自然语言处理2 1 2 自然语言处理的任务 已剪辑自 https mp weixin qq com s hSTkA2ffa1YWCoZOgQdrBQ 本文系书稿选登 2 1
  • Ubuntu安装JLink_Linux_V434a & eclipse for c/c++

    按照网上说法 xff1a 由于ubuntu电脑使用usb口来连接Jlink 因此首先要安装usb的库 使用apt get install libusb命令无法定位到libusb软件 xff0c 于是 下载并安装 http sourcefor
  • 详解C语言二级指针三种内存模型

    已剪辑自 https mp weixin qq com s LRMjzIYIVPs6x6ja5ffp w 二级指针相对于一级指针 xff0c 显得更难 xff0c 难在于指针和数组的混合 xff0c 定义不同类型的二级指针 xff0c 在使
  • 可参考的通信数据接收解析方法

    已剪辑自 https mp weixin qq com s ZwAlQv1wV4M3ivCv4wKakw 前阵子一朋友使用单片机与某外设进行通信时 xff0c 外设返回的是一堆格式如下的数据 xff1a AA AA 04 80 02 00
  • 嵌入式软件测试怎么实现自动化测试?

    我是做嵌入式自动化测试的 xff0c 我来回答下吧 题主你的表达有点混乱 xff0c 我挑出来三个问题 xff1a 1 希望做测试做的高大上 2 不用手工这么累 3 测试做出能看到前景 我也做测试 xff0c 虽然自以为也不很高大上 第一个
  • 嵌入式软件自动化测试方法

  • STM32 | hex文件、bin文件、axf文件的区别?

    已剪辑自 https mp weixin qq com s 1EQRooYYpDeKvHpqguik6w 在STM32开发中 xff0c 经常会碰到hex文件 bin文件与axf文件 xff0c 这些都是可以烧写到板子里运行的文件 这三个文
  • 嵌入式 C 语言进阶小技巧,弱符号和弱引用

    已剪辑自 https mp weixin qq com s 7gBn4CB PwiJBfM0v57 xA 我是老温 xff0c 一名热爱学习的嵌入式工程师 关注我 xff0c 一起变得更加优秀 xff01 工程师老温 xff
  • 单片机开发中,传感器的数据处理算法

    已剪辑自 https mp weixin qq com s Yy7ysMXoeokW2g yaqsw3w 在传感器使用中 xff0c 我们常常需要对传感器数据进行各种整理 xff0c 让应用获得更好的效果 xff0c 以下介绍几种常用的简单
  • 功能安全软件架构

    已剪辑自 https mp weixin qq com s pCenGTqg2Xi t7b8ebNHMA 1 E GAS 安全架构思想 汽车功能安全旨在把电子电气系统失效而导致的人身危害风险控制在合理范围内 下图是常见的电子电气系统硬件构成
  • 代码是如何控制硬件的?

    简单来说 xff0c 就是软件指令通过操作寄存器 xff0c 控制与 或 非门搭建的芯片电路 xff0c 产生 保存高低电平信号 xff0c 实现相应的逻辑 xff0c 最终通过IO 串口等输出 要想更清楚的了解软件控制硬件的原理 xff0
  • Windows下的TCP/UDP网络调试工具-NetAssist以及Linux下的nc网络调试工具

    已剪辑自 https blog csdn net ccf19881030 article details 109370384 一 Windows下的网络调试工具 NetAssist 1 TCP服务端和客户端测试2 UDP服务端和客户端测试
  • 软件产品化

    1 产品化定义 xff1a 软件产品化是指客户无需为软件添加或调整代码和语句即能完成软件的安装配置 应用初始化 系统管理 用户使用的全过程 xff0c 并且软件至少能满足80 以上的用户某一组应用需求 微软Office或杀毒软件就是产品化软
  • 使用Dev C++进行Windows socket网络编程,需链接lws2_32库

    背景 在我们使用Dev C 43 43 进行C语言编程时 xff0c 如果我们引入的库是C语言标准库 xff0c 那我们是不要在编译器选项中进行额外的设置的 xff0c 但是如果我们使用的是一些不是C语言标准库 xff0c 那我们可能就需要

随机推荐