C和C++如何实现互相调用详解

顾言
顾言
发布时间:2026-10-16| 4人浏览过
原创

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++互操作、混合编程的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。