0%

extern C 用法

extern C 作用

1
2
3
4
5
6
7
8
9
#ifdef __cplusplus
extern "C" {
#endif
// 函数声明
// 或者函数定义
// 或者#include <C语言Header.h>
#ifdef __cplusplus
}
#endif

extern "C"修饰的变量和函数按照 C 语言方式编译和连接

Cpp 和 C 编译的编译方式是不同的,比如对于相同的函数原型: void foo(int x, int y)

C 语言中该函数被编译后在符号库中的名字是_foo

Cpp 中,函数被编译器编译后,在符号库中的名字会带上参数类型, 会产生像_foo_int_int(不同编译器可能生成的名字不同, 但都使用相同机制) 之类的名字

Cpp 也是依靠这种机制实现函数重载的

extern "C" 的作用就是指示编译器, 将其修饰或包含的代码按照 C 语言方式编译,编译后的函数符号不包含参数类型, 也正是因为这个,extern "C"中包含的代码不能包含重载函数

C 与 Cpp 中的使用

C 语言中调用 Cpp 代码

当 Cpp 导出 C 语言格式的函数后,不仅 C 语言可以调用 Cpp 的函数; Cpp 编写的函数库 (lib/dll/a/so), 也可以以 C 语言函数接口为标准, 提供给其它语言使用,比如 Python, C# 或者 Lua 等, 以此实现多语言之间的混合使用 Cpp 头文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// cpph.h
#ifndef CPPH_H
#define CPPH_H

// 只在C++中让extern "C"出现, C语言不支持该语法
// 用__cplusplus宏判断后, C++和C中可以共用这份头文件
// 即使编译为运行库, 也需要一份可以共用的接口头文件
#ifdef __cplusplus
extern "C" {
#endif
int add(int x, int y);
#ifdef __cplusplus
}
#endif

#endif

Cpp 实现源码 (或者实现的函数库 lib/dll)

1
2
3
4
5
// cpph.cc
#include "cpph.h"
int add(int x, int y) {
return x + y;
}

C 语言文件

1
2
3
4
5
6
7
// c_file.c
#include <stdio.h>
extern int add(int x, int y); // 或者#include "cpph.h", 包含Cpp头文件
void main() {
int result = add(3, 5);
printf("%d\n", result);
}

Cpp 中调用 C 代码

C 头文件

1
2
3
4
5
// chead.h
#ifndef CHEAD_H
#define CHEAD_H
extern int add(int x, int y);
#endif

C 源文件

1
2
3
4
5
// chead.c
#include "chead.h"
int add(int x, int y) {
return x + y;
}

Cpp 中调用

1
2
3
4
5
6
7
8
9
10
#include <iostream>
// 或者 extern "C" int add(int x, int y);
extern "C" {
#include "chead.h"
}
int main() {
int c = add(100, 200);
std::cout << c << std::endl;
return 0;
}