CPP和C文件混合编译问题

本文探讨了C++与C的混合编程方法,介绍了__cplusplus和externC的使用策略,以及在不同情况下(C库+C++源码或C++库+C源码)如何正确编译链接,以确保代码的兼容性和有效性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.1 为什么需要混合编程
Cpp是从C演变过来的,C有很多优秀成熟项目和库,没必要在C++中重写,C++程序可以直接调用调用
庞大项目划分后一部分适合用C(底层),一部分适合用C++(中间层、上层)
1.2 混合编程的支撑
编译型程序的编译过程:源文件->目标(库)文件->可执行程序->镜像文件
任何编程语言执行时都必须是可执行程序,所以都必须先被编译成目标文件
混合编程的“混合”操作发生在链接这一步

二、C和C++混合编程的解决方案
通过前面的研究我们可以知道C和C++本质上是可以混合编程的,但是生成的中间符号名称不同,所以链接器在进行链接时会出问题,那如何解决呢?

2.1 先谈谈__cplusplus
__cplusplus是C++中预定义的一个标准宏,为长整型,其值为cpp标准的年月;在C中是未进行定义的,可以用来检测编译环境

2.2 extern “C”{}
用extern “C”{}可以使{}中的内容用C的标准来编译

#ifndef __TEST_H_
#define __TEST_H_

#ifdef __cplusplus
extern "C"
{
#endif
    int func1();
#ifdef __cplusplus
}
#endif
#endif

2.3 解决方案
通过2.2我们可以知道在C++的头文件中只要把函数的声明放在extern “C”{}的大括号范围之内,就可以让g++在编译这个函数时生成中间符号名时按照C的规则而不是按照C++的规则,所以这样的函数就可以和C的库进行共同链接。但是,在C语言中,extern “C”{}是未被定义的

所以我们将__cplusplus和extern “C”{}结合使用,通常有以下两种情况:

三、两种常见情况
3.1 同一个项目中C是库,C++是源码,C++调用C
这是最常见的情况,我们只需要在C的头文件中加上extern "C"的声明,在C++中直接包含头文件调用。后继直接用g++编译链接即可

如果我们同时有C和Cpp的源码,我们也是只需要在C的.h库函数中加入__cplusplus和extern “C”{},对于Cpp的.hpp文件不做任何改动,最后统一进行g++编译即可

g++ main.cpp test.c  -o main.elf

3.2 同一个项目中C++是库,C是源码,C调用C++
如果我们只有C++库而源码是C,我们最后只能用gcc编译链接,这带来了很多麻烦:

gcc main.c -c -o main.o
g++ test. -c -o test.cpp.o
gcc main.o test.cpp.o  -o main.elf

g++和gcc的编译时符号差异
c++支持很多c并不支持的特性,如函数重载
而C++继承了C的所有特性,也就是说C编译时无法直接像C++一样使用特定的语句实现编译Cpp时按照C的规则。但是,我们可以用cpp写一层封装层,加上extern “C”,

#ifndef __TEST_H_
#define __TEST_H_

#ifdef __cplusplus
extern "C"
{
#endif
    int func1();
#ifdef __cplusplus
}
#endif
#endif

在只有C++库而源码是C的情况下,使用封装层的技巧就是封装层使是用g++编译,但是只在封装头文件函数声明中加了extern “C”,而调用的C++静态库函数的#include未加,因此调用的函数还是按C++的规则解析,制作库时可以实现连接。在C源码中调用封装库,巧妙避免了直接使用C++库由于临时符号不同导致的链接错误

总之,
源码是CPP,调用库是C,只用g++ 编译;
源码是C,调用库是CPP,CPP的头文件加入

#ifdef __cplusplus
extern "C"
{ 

}
用g++ -c *.cpp -o **.cpp.o  生成cpp.o
用gcc -c main.c -o main.o   生成c.o
gcc main.o **.cpp.o -o target.elf  生成最终文件
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值