extern "C"用于解决C与C++混合编程中的链接问题,因C++支持函数重载会进行名称修饰,而C语言不会。通过extern "C"声明,可使C++编译器以C语言的命名和调用约定处理函数,确保符号名一致,实现双向调用。在C++中调用C函数时,需在包含头文件时使用extern "C"包裹声明;为让C调用C++函数,则需在C++函数前加extern "C"并避免使用C++特有特性。常见做法是在头文件中使用#ifdef __cplusplus宏判断,自动兼容两种语言。注意extern "C"不适用于类成员函数或函数重载,且编译时应确保C++文件用g++编译并正确链接。

在C++项目中调用C语言代码,或者让C语言代码使用C++编写的函数时,经常会遇到链接错误。这是因为C++支持函数重载,会对函数名进行名称修饰(name mangling),而C语言不会。为了解决这个问题,C++提供了 extern "C" 机制,用来告诉编译器以C语言的方式处理函数声明和链接。
什么是 extern "C"
extern "C" 并不是C语言的关键字,而是C++为实现与C语言兼容而引入的一种语法。它指示编译器:这部分函数或变量应按照C语言的规则进行编译和链接,即不进行名称修饰,使用C的调用约定。 这样做的结果是,C++生成的目标文件中,这些函数的符号名与C语言一致,从而允许C代码正确调用它们,反之亦然。在C++中调用C语言函数
假设你有一个C语言编写的函数,定义在 my_c_func.c 和头文件 my_c_func.h 中:my_c_func.h:
#ifndef MY_C_FUNC_H #define MY_C_FUNC_H void hello_from_c(void); #endif
my_c_func.c:
#include现在你想在C++代码中调用 hello_from_c(),你需要在包含该头文件时使用 extern "C" 来防止C++对函数名进行修饰。#include "my_c_func.h" void hello_from_c(void) { printf("Hello from C!\n"); }
main.cpp:
立即学习“C语言免费学习笔记(深入)”;
extern "C" {
#include "my_c_func.h"
}
int main() {
hello_from_c();
return 0;
}
或者,更常见的写法是在头文件中同时兼容C和C++:
修改 my_c_func.h:
#ifndef MY_C_FUNC_H
#define MY_C_FUNC_H
#ifdef __cplusplus
extern "C" {
#endif
void hello_from_c(void);
#ifdef __cplusplus
}
#endif
#endif
这样,无论被C还是C++包含,都能正确处理。C++编译器会识别 __cplusplus 宏并加上 extern "C",而C编译器则忽略这部分内容。
让C语言调用C++函数
这种情况较少见,但也是可行的。前提是被调用的C++函数不能使用C++特有特性(如类、重载、引用等),并且需要用 extern "C" 声明为C风格链接。my_cpp_func.cpp:
extern "C" void hello_from_cpp(void) {
// 只能使用C可调用的内容
printf("Hello from C++!\n");
}
注意:这个函数虽然写在C++文件中,但通过 extern "C" 声明,其符号名不会被修饰。
main.c(C语言主程序):
#include编译时需要先编译C++文件,再与C文件链接:// 声明外部函数 extern void hello_from_cpp(void); int main() { hello_from_cpp(); return 0; }
gcc -c main.c g++ -c my_cpp_func.cpp g++ main.o my_cpp_func.o -o program
注意事项和常见问题
- 不能用于C++类成员函数:extern "C" 只适用于自由函数(非成员函数),因为C不支持类。
- 不能重载用 extern "C" 声明的函数:C语言不支持重载,因此即使在C++中也不能为 extern "C" 函数提供多个版本。
- 头文件中正确使用 __cplusplus 宏:这是保证头文件同时被C/C++安全包含的标准做法。
- 链接时确保目标文件正确生成:C++源文件需用g++编译,C文件用gcc或g++均可,但最终链接建议用g++以处理C++运行时。
基本上就这些。只要在混合编程时注意函数声明方式和编译链接流程,extern "C" 能很好地解决C与C++之间的互操作问题。










