C和C++如何实现互相调用详解
C与C++混合开发时,常因两者编译规则差异导致链接失败。掌握extern "C"的使用以及正确处理__cplusplus宏,是解决这一问题的关键。本文通过具体代码示例演示C与C++的相互调用方法及注意事项。
C与C++为何无法直接互相调用?
在项目开发中,底层组件多使用C实现,而上层应用采用C++。要实现二者的互通,必须理解其底层的差异:
- 编译工具不同:
.c文件通常使用gcc编译,而.cpp文件使用g++编译。 - 名称修饰(Name Mangling):为了支持函数重载特性,
C++编译器在生成目标文件时会对函数名进行加工,使其包含参数类型等额外信息;而C语言编译器生成的函数名则保持原样。
由于符号表中的函数名不一致,C++代码无法直接链接到C编写的函数,反之亦然。解决这个问题需要借助extern "C"机制。
第1步:准备工作
目的:创建测试环境,观察C与C++编译后的符号差异。
操作:准备cal.c、cal.h和main.cpp三个文件,cal.c中定义一个简单函数embedded_art。
结果:准备好待编译的源文件。
第2步:编译并检查符号表
目的:验证C与C++编译后的函数名差异。
操作:分别运行gcc -c cal.c和g++ -c main.cpp生成目标文件,并使用nm或相关工具查看cal.o中的符号表。
重要参数:-c仅编译不链接。
状态:g++输出的符号表中,函数名已被修饰过,而gcc则为原始名。
第3步:C++调用C的正确方式
目的:让C++正确识别并调用C函数。
入口:打开main.cpp文件。
动作:在引入C头文件的位置包裹extern "C"块,强制C++编译器以C语言规则解析声明的函数。
代码示例:
extern "C" {
#include "cal.h"
}
完成状态:再次编译并链接所有目标文件,即可生成可执行文件并正常运行。
完整编译与运行流程(Ubuntu环境):
$ ls cal.c cal.h main.cpp $ gcc -c cal.c $ g++ -c main.cpp $ ls cal.c cal.h cal.o main.cpp main.o $ g++ main.o cal.o $ ./a.out main entry 嵌入式艺术
C如何调用C++?
场景反转:当我们需要在.c文件中调用由C++实现的逻辑时,同样面临函数名修饰的问题。这次我们需要确保C++生成的符号表符合C的规范。
第4步:初步尝试
操作:准备cal.cpp(含函数定义)、cal.h和main.c。
动作:使用g++ -c cal.cpp和gcc -c main.c分别编译。
现象:如果直接在cal.h中写extern "C"并在main.c中包含它,会导致编译错误。
第5步:解决C中的语法错误
原因分析:关键字extern "C"是C++特有语法,标准C语言编译器(gcc)无法识别,会报错。
方案:利用预处理器宏__cplusplus来判断当前是哪种编译器环境。仅在C++环境下插入extern "C"。
修改cal.h文件:
#ifdef __cplusplus
extern "C" {
#endif
void embedded_art(void);
#ifdef __cplusplus
}
#endif
效果:C++编译cal.cpp时使用C命名规则生成符号,而gcc编译main.c时忽略这些预处理指令,不会报错。
第6步:重新编译与链接
操作:修改头文件后,重新编译并链接,最终运行程序。
完整操作流程:
$ g++ -c cal.cpp $ gcc -c main.c $ # 注意:部分Linux发行版gcc默认开启PIE链接,可能导致问题,建议显式关闭或使用g++链接 $ gcc -no-pie cal.o main.o -o main $ ./main main entry 嵌入式艺术
进阶技巧:不使用中间层修改源文件
如果无法修改原有的C++源码(例如它是第三方库),可以采用“中间层”策略。创建一个新的C++文件(如wrapper.cpp)作为桥梁。
1. 原有逻辑(不可改):
// max.cpp (C++)
int Max(int a, int b) { return a > b ? a : b; }
2. 中间层包装:
// wrapper.cpp (C++)
extern "C" {
int MyMax(int a, int b) {
return Max(a, b); // 内部用C++逻辑
}
}
3. C文件调用:
// main.c (C)
int MyMax(int, int);
int main() {
printf("%d\n", MyMax(10, 20));
return 0;
}
关键点:中间层本质上是一个C++文件,所以它内部可以直接调用普通C++函数,同时对外暴露extern "C"接口供C调用。
总结
C与C++之间的相互调用,核心在于统一两边的编译规则。通过使用extern "C"阻止C++的名称修饰,并利用__cplusplus宏保证兼容性,即可顺利打通两种语言之间的壁垒。以上就是C和C++如何实现互相调用的详细内容,更多关于C与C++互操作、混合编程的资料请关注本站其它相关文章!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









