一、extern “C” 怎么使用
介绍 extern “C”
我正在探讨如何在 C++ 中使用
extern "C",以防止名称修饰和实现与 C 的互操作性。这涉及到函数声明、头文件和链接等内容。
extern "C" 是 C++ 中用于指定使用 C 语言的链接方式(链接规范)的声明修饰符。它主要用于实现 C++ 与 C 代码之间的互操作性,避免由于 C++ 的名称修饰(Name Mangling)导致的链接错误。通过使用 extern "C",可以确保 C++ 编译器生成的函数名称与 C 语言的名称保持一致,从而实现两者之间的无缝调用。
1.1 为什么需要 extern "C"
C++ 支持函数重载和命名空间等特性,这导致编译器在生成符号时会进行名称修饰(Name Mangling),使得同名但参数不同的函数能够共存。而 C 语言不支持函数重载,编译器不会对函数名称进行修饰。因此,当需要在 C++ 中调用 C 函数或将 C++ 函数暴露给 C 时,名称修饰会导致链接错误。这时,extern "C" 就显得尤为重要。
1.2 extern "C" 的基本用法
1. 在 C++ 中调用 C 函数
假设有一个 C 语言编写的库,包含以下函数:
C 语言代码(example.c)
// example.c
#include <stdio.h>
void hello() {
printf("Hello from C!\n");
}
C++ 代码(main.cpp)
// main.cpp
#include <iostream>
// 使用 extern "C" 声明 C 函数
extern "C" {
void hello();
}
int main() {
hello(); // 调用 C 函数
return 0;
}
编译和链接
# 编译 C 代码
gcc -c example.c -o example.o
# 编译 C++ 代码
g++ -c main.cpp -o main.o
# 链接生成可执行文件
g++ main.o example.o -o my_program
运行 my_program 会输出:
Hello from C!
2. 在 C++ 中定义可以被 C 调用的函数
C++ 代码(library.cpp)
// library.cpp
#include <iostream>
extern "C" void greet(const char* name) {
std::cout << "Hello, " << name << " from C++!" << std::endl;
}
C 语言代码(main.c)
// main.c
#include <stdio.h>
// 声明 C++ 函数
void greet(const char* name);
int main() {
greet("C Programmer");
return 0;
}
编译和链接
# 编译 C++ 代码
g++ -c library.cpp -o library.o
# 编译 C 代码
gcc -c main.c -o main.o
# 链接生成可执行文件
g++ main.o library.o -o my_program
运行 my_program 会输出:
Hello, C Programmer from C++!
1.3 在头文件中使用 extern "C"
为了方便 C++ 和 C 之间的互操作,通常会在头文件中使用条件编译来包含 extern "C",以确保在 C++ 编译器下使用 C 的链接规范,而在 C 编译器下不使用。
头文件示例(example.h)
// example.h
#ifndef EXAMPLE_H
#define EXAMPLE_H
#ifdef __cplusplus
extern "C" {
#endif
void hello();
void greet(const char* name);
#ifdef __cplusplus
}
#endif
#endif // EXAMPLE_H
这样,无论是 C 还是 C++ 编译器包含此头文件,都能正确处理函数声明。
1.4 注意事项
- 仅用于函数声明:
extern "C"主要用于函数的声明和定义,不适用于类、模板等 C++ 特有的特性。 - 名称修饰:使用
extern "C"可以防止名称修饰,但需要确保函数的参数和返回类型在 C 和 C++ 中兼容。 - 内联函数:C++ 的内联函数不能被
extern "C"修饰,因为 C 不支持内联函数。 - 变量声明:虽然可以使用
extern "C"来声明变量,但需要小心处理全局变量的命名和初始化,确保与 C 代码的一致性。
1.5 更复杂的示例:C++ 类与 C 的互操作
由于 C 不支持类,通常通过 C++ 提供的 C 接口来操作类对象。这涉及到封装类指针并通过 C 接口进行操作。
C++ 类(MyClass.h 和 MyClass.cpp)
// MyClass.h
#


1299

被折叠的 条评论
为什么被折叠?



