目录
一、extern "C"是什么?
在C++中,extern "C"
是一个指示符,用于告诉编译器按照C语言的规则对代码进行处理,而不是C++的规则。这在与C代码进行交互时非常有用,因为C和C++有不同的名称修饰和函数调用约定。
具体来说,extern "C"
用于声明C语言风格的函数接口,这意味着函数名称不会被C++的名称修饰机制修改,也就是不会进行函数名称的重命名(名称修饰)。这样做可以确保C++代码可以正确地调用C语言编写的函数,因为C++和C语言之间的函数调用约定可能不同。
例如,假设有一个C语言函数声明如下:
// C语言代码
int c_function(int arg);
如果在C++中包含这个C语言头文件,并使用extern "C"
声明,那么C++编译器将不会修改函数名称:
// C++代码
extern "C" {
#include "c_library.h"
}
int main() {
int result = c_function(10);
return 0;
}
这样,编译器就不会将 c_function
的名称进行修改,从而确保正确调用C语言的函数。
二、C++调用C语言编写的.so库
在C++中调用一个C语言编写的 .so
(共享对象)库并不复杂,因为C++和C都可以使用C的函数调用约定。下面是一个简单的步骤:
1.包含头文件:首先,在C++代码中包含要使用的C语言库的头文件。
extern "C" {
#include "your_c_library.h"
}
使用 extern "C"
声明告诉编译器这些函数是用C语言编写的,而不是C++。这样,编译器就会使用C的函数调用约定来调用这些函数。
2.链接库文件:确保在链接阶段将C语言库的 .so
文件链接到您的C++代码中。
g++ your_cpp_code.cpp -o your_program -lyour_c_library
在这个例子中,-lyour_c_library
选项告诉编译器链接名为 libyour_c_library.so
的库文件。
3.调用C语言函数:现在您可以在C++代码中直接调用C语言函数。
int result = c_function_name(arguments);
可以像调用任何其他函数一样调用C语言函数,只需使用其函数名和参数列表。
4.使用命名空间(可选):如果C语言库中有许多函数,您可以将它们放在C++的命名空间中,以防止与其他库发生命名冲突。
namespace MyCLibrary {
extern "C" {
#include "your_c_library.h"
}
}
然后,可以这样调用函数:
int result = MyCLibrary::c_function_name(arguments);
这些步骤应该能够在C++代码中成功调用一个C语言编写的.so
库。
三、C引用C++中的全局函数
如果 C 代码需要引用 C++ 中的全局函数,而这些函数被声明为 extern "C"
,那么 C++ 的头文件中确实需要使用 extern "C"
来声明这些函数。
假设有一个 C++ 头文件 functions.h
,其中声明了一个全局函数,并且这个函数被用 extern "C"
修饰,以确保其名称在链接时按照 C 语言规则进行修饰,那么在 C 代码中包含这个头文件时,需要正确处理这个声明:
// functions.h
#ifndef FUNCTIONS_H
#define FUNCTIONS_H
#ifdef __cplusplus
extern "C" {
#endif
void globalFunction(); // 声明一个全局函数
#ifdef __cplusplus
}
#endif
#endif
在 C++ 实现文件中实现这个函数,并在需要的时候包含这个头文件:
// functions.cpp
#include "functions.h"
#include <iostream>
// 实现全局函数
void globalFunction() {
std::cout << "Hello from globalFunction() in C++!" << std::endl;
}
在 C 代码中包含这个头文件,并调用这个函数:
// main.c
#include "functions.h"
int main() {
// 调用全局函数
globalFunction();
return 0;
}
这样,当 C 代码调用 globalFunction()
时,会按照 C 语言的规则进行链接,确保能够正确地调用 C++ 中的全局函数。
在这种情况下,C 可以使用 extern
关键字来引用 C++ 中的全局函数,但是如果 C++ 的全局函数被声明为 extern "C"
,那么在 C 代码中不需要使用 extern
关键字。
extern
关键字主要用于告诉编译器某个变量或函数是在别处定义的,而不是在当前文件中定义。当 C++ 的全局函数被声明为 extern "C"
时,这个函数的名称在链接时会按照 C 语言规则进行修饰,因此在 C 代码中可以直接引用这个函数而不需要使用 extern
。
举例来说,如果在 C++ 中有一个全局函数声明如下:
// functions.h
#ifndef FUNCTIONS_H
#define FUNCTIONS_H
#ifdef __cplusplus
extern "C" {
#endif
void globalFunction(); // 声明一个全局函数
#ifdef __cplusplus
}
#endif
#endif
那么在 C 代码中可以直接调用 globalFunction()
,而不需要使用 extern
:
// main.c
#include "functions.h"
int main() {
// 调用全局函数
globalFunction();
return 0;
}
四、C++语言规则和C语言规则有什么不同?
C++ 和 C 语言在许多方面有所不同,其中一些重要的区别包括面向对象编程、函数重载、命名空间和异常处理。下面是一些具体的示例说明:
1.面向对象编程:
-
C++ 是一种面向对象的语言,支持类和对象的概念,可以使用类来组织数据和函数。例如:
// C++ 中的类定义和使用
class Car {
private:
string brand;
string model;
int year;
public:
Car(string b, string m, int y) : brand(b), model(m), year(y) {}
void displayInfo() {
cout << "Brand: " << brand << ", Model: " << model << ", Year: " << year << endl;
}
};
int main() {
Car myCar("Toyota", "Corolla", 2022);
myCar.displayInfo();
return 0;
}
- C 语言不支持类和对象的概念,因此无法进行面向对象编程。
2.函数重载:
-
C++ 支持函数重载,允许在同一个作用域内定义多个同名函数,只要它们的参数列表不同即可。例如:
// C++ 中的函数重载
int add(int a, int b) {
return a + b;
}
double add(double a, double b) {
return a + b;
}
int main() {
cout << add(5, 3) << endl; // 输出 8
cout << add(3.5, 2.5) << endl; // 输出 6
return 0;
}
- C 语言不支持函数重载,因此同一作用域内不允许定义多个同名函数。
3.命名空间:
-
C++ 引入了命名空间的概念,允许将变量、函数和类组织到命名空间中,以避免命名冲突。例如:
// C++ 中的命名空间
namespace Math {
int add(int a, int b) {
return a + b;
}
}
int main() {
cout << Math::add(5, 3) << endl; // 输出 8
return 0;
}
- C 语言不支持命名空间,因此所有的全局变量和函数都处于同一个命名空间内。
4.异常处理:
-
C++ 提供了异常处理机制,可以使用 try-catch 块来捕获和处理程序中的异常。例如:
// C++ 中的异常处理
int divide(int a, int b) {
if (b == 0) {
throw "Division by zero!";
}
return a / b;
}
int main() {
try {
int result = divide(10, 0); // 试图除以0,抛出异常
} catch (const char* msg) {
cerr << "Error: " << msg << endl; // 捕获异常并输出错误信息
}
return 0;
}
- C 语言不支持内置的异常处理机制,通常通过返回特殊值或设置全局错误代码来处理错误。
五、extern的注意事项
使用 extern
关键字时需要注意以下几点:
声明与定义的分离:
extern
只是声明一个变量或函数,而不是定义它。因此,在使用extern
声明时,需要确保在其他地方有对应的定义。作用域问题:
extern
声明的变量或函数具有全局作用域,可以在整个程序中访问。变量声明: 对于变量的
extern
声明,只是告诉编译器该变量是在其他文件中定义的,而不是在当前文件中定义的。函数声明: 对于函数的
extern
声明,通常用于引用其他文件中定义的函数。这种声明方式可以使得多个文件共享同一个函数定义,而不需要重复定义。常量声明: 在 C++ 中,对于
extern
声明常量,必须使用const
关键字。这样声明的常量是一个声明而非定义,编译器在编译时不会为它分配存储空间,而是将其作为一个标识符,用于在其他文件中访问已定义的常量。注意链接问题:
extern
声明的变量或函数在链接时需要确保有对应的定义,否则会导致链接错误。
做大做强,再创辉煌!