在 C++ 编程中,extern "C"是一个非常重要的特性,它主要用于解决 C++ 与 C 代码之间的相互调用问题。本文将深入探讨extern "C"的作用、使用原因以及具体的使用方法。
一、extern "C" 的作用
extern "C"的主要作用是告诉 C++ 编译器,按照 C 语言的方式来编译和链接指定的代码。在 C++ 中,函数名会被编译器进行名字改编(Name Mangling),这是为了支持函数重载等特性。而 C 语言没有函数重载,函数名不会被改编。当我们需要在 C++ 代码中调用 C 语言编写的函数,或者在 C 语言代码中调用 C++ 编写的函数时,就需要使用extern "C"来确保函数名在编译和链接过程中的一致性。
C++ 中函数名修饰的格式和规则
C++ 的名字修饰规则,是为了让编译器能够区分同名但参数列表不同的函数,进而实现函数重载。不同的编译器,其名字修饰规则可能存在差异 ,这里以常见的 GCC 编译器为例展开说明。需注意,实际的修饰规则在不同版本编译器以及不同编译选项下可能有所变化,以下展示的规则不一定完全正确,但基本遵循这个思路。。
对于一个简单的函数定义:
void func(int a, double b);
GCC 编译器可能会将其修饰为类似这样的形式:
_Z4funcid
其中:
- _Z是名字修饰的前缀,是 GCC 编译器的约定。
- 4表示函数名func的长度。
- func即原函数名。
- i表示第一个参数是int类型。
- d表示第二个参数是double类型。
如果函数是类的成员函数,情况会更复杂一些。例如:
class MyClass {
public:
void memberFunc(int a, double b);
};
其修饰后的名字可能类似:
_ZN7MyClass9memberFuncidE
这里:
- _Z同样是前缀。
- N表示接下来是一个命名空间或者类的名字。
- 7表示类名MyClass的长度。
- MyClass是类名。
- 9表示成员函数名memberFunc的长度。
- memberFunc是成员函数名。
- i和d含义同前,分别表示参数类型。
- E表示名字结束。
这种复杂的名字改编机制,使得编译器能够在编译和链接阶段准确区分不同的函数,即使它们名字相同,只要参数列表不同就能被正确识别。但在 C 语言中,由于没有这种需求,函数名就是简单的标识符,不进行如此复杂的改编 。这就是为什么在 C++ 与 C 语言混合编程时,需要extern "C"来消除这种差异。
二、使用 extern "C" 的原因
兼容性:在实际项目中,很多成熟的库都是用 C 语言编写的,例如一些操作系统底层的库、数学计算库等。C++ 作为一种更高级的语言,希望能够复用这些 C 语言库的代码。通过extern "C",C++ 可以无缝地调用 C 语言的函数,实现两者的兼容。
保持代码简洁:如果不使用extern "C",在 C++ 中调用 C 函数时,需要进行复杂的函数声明和链接设置,这会使代码变得繁琐。而extern "C"简化了这个过程,使代码更加简洁易读。
三、extern "C" 的使用方法
- 在 C++ 中调用 C 函数
-
- 首先,编写一个 C 语言的源文件,例如c_function.c:
#include <stdio.h>
// C语言函数定义
void c_function() {
printf("This is a C function.\n");
}
- 然后,在 C++ 源文件中调用这个 C 函数,例如cpp_main.cpp:
extern "C" {
// 声明要调用的C函数
void c_function();
}
int main() {
c_function();
return 0;
}
在这个例子中,extern "C"将c_function函数的声明按照 C 语言的方式进行处理,这样 C++ 编译器就能够正确地找到并调用这个 C 函数。
- 在 C 语言中调用 C++ 函数
-
- 编写一个 C++ 的源文件,例如cpp_function.cpp:
#include <iostream>
// C++函数定义
extern "C" void cpp_function() {
std::cout << "This is a C++ function called from C.\n";
}
- 然后,在 C 语言源文件中调用这个 C++ 函数,例如c_main.c:
// 声明要调用的C++函数
extern void cpp_function();
int main() {
cpp_function();
return 0;
}
这里cpp_function函数被声明为extern "C",这样 C 语言编译器就能够识别并调用这个 C++ 函数。