cpp 程序与 c 程序的相互调用(extern “C“ 的使用)

news2024/10/7 18:27:59

实际在编译的过程中,.cpp 文件调用 .c文件中的函数会出错。假设代码结构如下:


目录

一、编译过程分析

1、预处理

2、编译

3、汇编

4、链接

二、问题解决

1、解决方案

2、解决思路


一、编译过程分析

1、预处理

该阶段头文件会被展开,此时只剩下 Add.c 和 main.cpp 文件。

2、编译

该阶段除了做一些语法、词法、语义分析、转换成汇编代码外,还会进行符号汇总

3、汇编

该阶段的目的是将汇编代码转换成二进制机器码,除此之外,还会生成符号表。符号名的修饰规则依赖于使用的编译器。.cpp 文件默认使用的是 c++编译器, 而 .c 文件默认使用的是 c 编译器

  • C 编译器的命名规则:直接将函数名作为符号名,不做任何修饰
  • C++编译器的命名规则:__Z + 返回值类型 + 函数名 + 形参类型

4、链接

在这个阶段,我们目前只关注一个功能,那就是将不同来自不同源文件的符号表汇总

汇总以后发现,main.cpp 中用到了 Add 函数,因为在 .cpp 文件中,那么经过C++编译器生成的符号名就是__ZiAddii ,结果发现找不到对应的函数地址,这个时候就会报错。

VS环境下的报错是:

Linux环境下的报错是: 

二、问题解决

下面先贴出解决方案,至于原因,感兴趣的可以继续往下看

1、解决方案

只要将函数声明放在下面指示的地方即可

#ifdef __cplusplus
extern "C" {
#endif

	// 你的函数声明

#ifdef __cplusplus
}
#endif

2、解决思路

最初的思路

根本原因在于 .c 文件和 .cpp 文件都引入了 Add.h,然而生成符号表的时候,却是使用了不同的命名规则,这就导致了得到了不同的符号名。

我们要保证的是,无论是 C 还是 C++ 编译器,得到的符号名是一样的,因此就引入了 extern "C",extern "C"可以保证自身作用域里的内容,是按照 C 编译器的修饰规则去编译的,这样的话得到的符号名就都是 C编译器的编译出来的结果。

extern "C" {
	int Add(int x, int y);
}

偶遇小坑

预处理阶段 Add.c 引入头文件 Add.h 并展开的时候,就变成了如下的样子,我们发现报错了,这是因为 C 程序虽然可以识别 extern 关键字,但是无法识别 extern "C" 这种形式

填坑!完事!

.cpp 文件和 .c 文件都会引入 Add.h 文件,cpp文件默认使用的是 C++编译器,而 c 文件默认使用的是C编译器,那我们的 Add.h 就有必要自己识别当前自己是在 cpp 文件被展开,还是在 c 文件被展开

这就要用到宏 __cplusplus,C++中定义了该宏,C却没有定义,因此如果在 cpp 文件中被展开,就需要加上 extern "C"; 如果是在 c 文件中被展开,就无需加上。

#ifdef __cplusplus
extern "C" {
#endif

	int Add(int x, int y);

#ifdef __cplusplus
}
#endif

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/444768.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

FPGA学习笔记(二):时序逻辑之计数器

与组合逻辑(给定输入,输出是确定的,与时间无关)相比较,时序逻辑不仅仅与输入信号相关,还与时钟信号相关。 D触发器:在上升沿时(CLK)才将输出(Q)修…

Failed to load property source from location ‘classpath:/application.yaml‘

问题 项目起动时,找不到yaml,各种处理还是没有解决,比如,clean,重启电脑,检查utf8等。 同事拉的新代码又是正常可以跑,这就有点奇怪了。 11:07:39.682 [main] ERROR org.springframework.boot.…

【19】linux进阶——后台运行()和nohup命令

大家好,这里是天亮之前ict,本人网络工程大三在读小学生,拥有锐捷的ie和红帽的ce认证。每天更新一个linux进阶的小知识,希望能提高自己的技术的同时,也可以帮助到大家 另外其它专栏请关注: 锐捷数通实验&…

分享自己接私活常用的开源系统

目前开源系统是JNPF框架。技术栈上是SpringBoot、SpringCloud、Spring Web、MyBatis、Swagger、Vue、Element。 这些都是比较主流的技术,无论是技术层面的先进性还是学习难度都是比较低的,目前网络上有大量可供参考学习的资料。 并且它支持前后端分离和…

Ceph入门到精通-Ceph如何扩展到超过十亿个对象?

Ceph如何扩展到超过十亿个对象?-ceph部署多少个节点 (51cto.com) 越来越多的组织被要求管理数十亿个文件和几百上千PB的数据。无论是在公共云还是本地环境中,Ceph对象存储都是值得考虑的一个选项。本篇文章将通过七部分的精选内容为下面这些问题提供答案…

vue3+echarts实现世界地图以及轨线(label使用fomatter+rich动态添加图片及背景色,以及label如何添加动态边框色)

背景 最近项目开发,需要开发一个世界地图,并且实现经纬度对应的点对点轨线动效,效果如下: 问题 如何在刚打开页面的时候就显示地点名称label如何同时添加图片和背景色label怎么动态修改字体颜色及图片以及动态边框色添加动效及…

YumRepo Error: All mirror URLs are not using ftp, http[s] or file解决办法

文章目录 一、问题背景二、问题原因三、解决方法 一、问题背景 CentOS6.5利用yum -y install gcc命令安装程序报错YumRepo Error: All mirror URLs are not using ftp, http[s] or file.Eg. Invalid release/repo/arch combination/ removing mirrorlist with no valid mirror…

maven安装教程(结合eclipse和IDEA)

一.安装maven 本文须知:安装maven环境之前要先安装java jdk环境(没有安装java环境的可以先去看安装JAVA环境的教程)Maven 3.3+ require JDK 1.7 及以上。 第一步:下载maven(本教程安装的是3.8.4) 官方下载链接:https://maven.apache.org/download.cgi Binary是可执行版本…

电子台账:生成的数据和图表导出到一个excel表中

目录 1 数据选择 1.1 选择1行数据 1.2 选择1列数据 2 图表设置 3 数据导出 为了便于进行数据分析和数据展示,可以把生成的汇总数据生成图表,然后对图表进行定制修改,最后把数据和图表一起导出到一个excel表中。 程序目前支持两种数据作…

【C++学习笔记】函数

值传递 值传递&#xff1a;函数调用时实参将数值传入给形参 做值传递时函数的形参发生改变&#xff0c;并不会影响实参 因为形参的作用域在函数内只有在调用函数时才会为其分配内存&#xff0c;函数调用结束后释放函数内的变量内存。 #include<iostream> using namespa…

mybatis04-mybatis缓存、分页插件、注解开发(一对一、多对一、多对多)

mybatis04 mybatis 缓存 一、mybatis 缓存概述 1、缓存 ​ 缓存 是存在于内存中的临时数据&#xff0c;使用缓存的目的是&#xff1a;减少和数据库的交互次数&#xff0c;提高执行效率。 2、mybatis 缓存 ​ mybatis 与 大多数的持久层框架一样&#xff0c;提供了缓存策略…

网络视频监控如何入门?如何安装和配置、设备选择和实时监控?

网络视频监控是一种先进的安全技术&#xff0c;它可以通过互联网连接到远程视频服务器&#xff0c;使用户可以随时随地监控所关注的地点。本文将介绍网络视频监控的基础入门知识&#xff0c;包括安装和配置、设备选择和实时监控等方面。 一、安装和配置 在进行网络视频监控前&…

PMP项目管理-[第五章]范围管理

范围管理知识体系&#xff1a; 规划范围管理&#xff1a; 收集需求&#xff1a; 定义范围&#xff1a; 创建WBS&#xff1a; 确认范围&#xff1a; 控制范围&#xff1a; 5.1 范围管理 产品范围&#xff1a;某项产品、服务或成果所具有的特性和功能 项目范围&#xff1a;为交付…

商品价格监控业务场景,API数据分析

商品价格监控指的是对特定商品价格进行实时监控和跟踪&#xff0c;及时更新最新价格并分析价格变化的行为。这种监控可以帮助企业及时了解市场行情&#xff0c;并根据价格变化情况做出相应的调整&#xff0c;以更好地应对市场变化。 一般来说&#xff0c;商品价格监控需要以下…

使用RabbitMq实现延迟队列

下载RabbitMq&#xff1a;本地安装rabbitmq_王胖胖1112的博客-CSDN博客 1、pom文件引入 <dependency> <groupId>org.springframework.amqp</groupId> <artifactId>spring-rabbit-test</artifactId> <scope>test&…

关于小程序云开发cms内容管理无法使用,无法同步内容模型到云开发数据库的解决方案

小程序官方最近又搞大动作了&#xff0c;偷偷的升级的云开发cms&#xff08;内容管理&#xff09;以下都称cms&#xff0c;不升级不要紧&#xff0c;这一升级&#xff0c;就导致我们没有办法正常使用cms了。如果你开通完cms带下面这个标识的话&#xff0c;就代表你是新版本&…

NVT | NVT SDK光敏电阻ADC配置与调试

NVT | NVT SDK光敏电阻ADC配置与调试 时间:2023-04-21 文章目录 `NVT` | `NVT` `SDK`光敏电阻`ADC`配置与调试1.参考2.电路原理图3.代码编写3-1.配置ADC通道3-2.初始化ADC3-3.ADC值读取3-4.ADC读取测试4.头文件1.参考 1.光敏电阻:原理及作用、符号及参数、选型及电路 2.

科技现代闪耀上海秀场 北京现代在上海车展上演转型之姿

4月18日&#xff0c;作为疫情后的第一个大型国际车展&#xff0c;第二十届上海国际汽车工业展览会盛况空前&#xff0c;新产品、新技术、新战略、新体验争先登台。作为合资企业的技术实力代表&#xff0c;北京现代不仅重磅发布了首款智能家居SUV车型MUFASA&#xff0c;并且以强…

微信小程序开发教程(二)--上传小程序

接上文,我们已经有一个小例子了。 在模拟器的位置,点击头像,会登录。 此时我们可以第一次尝试将我们的小程序进行上传。 点击下图箭头所指位置: 点击确定: 填写版本号和备注信息,选择上传: 在网页管理小程序上,选择上传,以下都选择红框所在位置:

多线段合并的两种方法:Cadance allegro与CAD交互

文章目录 问题引入Pe命令&#xff08;推荐&#xff09;block命令 问题引入 我们知道在Cadance allegro 中&#xff0c;涉及到板框文件和丝印层倒角的问题。而这些板框和丝印倒角的图形来自于CAD中的结构文件&#xff08;dxf文件&#xff09;&#xff0c;再导入到Cadance allegr…