extern


title: extern
date: 2021-06-20 17:07:22
tags: [C++]


extern

C++ 与 C 编译区别

在 C++ 中常在头文件见到 extern “C” 修饰函数,那有什么作用呢? 是用于C++链接在C语言模块中定义的函数。

C++ 虽然兼容 C,但 C++ 文件中函数编译后生成的符号与 C 语言生成的不同。因为 C++ 支持函数重载,C++ 函数编译后生成的符号带有函数参数类型的信息,而 C 则没有。

例如int add(int a, int b)函数经过 C++ 编译器生成 .o 文件后,add会变成形如add_int_int之类的, 而 C 的话则会是形如_add,就是说:相同的函数,在 C 和 C++ 中,编译后生成的符号不同。

这就导致一个问题:如果 C++ 中使用 C 语言实现的函数,在编译链接的时候,会出错,提示找不到对应的符号。此时extern "C"就起作用了:告诉链接器去寻找_add这类的 C 语言符号,而不是经过 C++ 修饰的符号。

C++ 调用 C 函数

C++ 调用 C 函数的例子: 引用 C 的头文件时,需要加extern "C"

//add.h
#ifndef ADD_H
#define ADD_H
int add(int x,int y);
#endif

//add.c
#include "add.h"

int add(int x,int y) {
    return x+y;
}

//add.cpp
#include <iostream>
#include "add.h"
using namespace std;
int main() {
    add(2,3);
    return 0;
}

编译:

//Generate add.o file
gcc -c add.c

链接:

g++ add.cpp add.o -o main

没有添加 extern “C” 报错:

> g++ add.cpp add.o -o main                                   
add.o:在函数‘main’中:
add.cpp:(.text+0x0): `main'被多次定义
/tmp/ccH65yQF.o:add.cpp:(.text+0x0):第一次在此定义
/tmp/ccH65yQF.o:在函数‘main’中:
add.cpp:(.text+0xf):对‘add(int, int)’未定义的引用
add.o:在函数‘main’中:
add.cpp:(.text+0xf):对‘add(int, int)’未定义的引用
collect2: error: ld returned 1 exit status

添加 extern “C” 后:

//add.cpp
#include <iostream>
using namespace std;
extern "C" {
    #include "add.h"
}
int main() {
    add(2,3);
    return 0;
}

编译的时候一定要注意,先通过gcc生成中间文件add.o。

gcc -c add.c 

然后编译:

g++ add.cpp add.o -o main

而通常为了 C 代码能够通用,即既能被 C 调用,又能被 C++ 调用,头文件通常会有如下写法:

#ifdef __cplusplus
extern "C"{
#endif
int add(int x,int y);
#ifdef __cplusplus
}
#endif

即在 C++ 调用该接口时,会以 C 接口的方式调用。这种方式使得 C++ 者不需要额外的 extern C,而标准库头文件通常也是类似的做法,否则你为何不需要 extern C 就可以直接使用 stdio.h 中的C函数呢?

C 中调用 C++ 函数

extern "C"在 C 中是语法错误,需要放在 C++ 头文件中。

// add.h
#ifndef ADD_H
#define ADD_H
extern "C" {
    int add(int x,int y);
}
#endif

// add.cpp
#include "add.h"

int add(int x,int y) {
    return x+y;
}

// add.c
extern int add(int x,int y);
int main() {
    add(2,3);
    return 0;
}

编译:

g++ -c add.cpp

链接:

gcc add.c add.o -o main

示例

综上,总结出使用方法,在 C 语言的头文件中,对其外部函数只能指定为 extern 类型,C 语言中不支持 extern “C” 声明,在 .c 文件中包含了 extern “C” 时会出现编译语法错误。所以使用 extern “C” 全部都放在于 cpp 程序相关文件或其头文件中。总结出如下形式:

C++ 调用 C 函数

//xx.h
extern int add(...)

//xx.c
int add(){
    
}

//xx.cpp
extern "C" {
    #include "xx.h"
}

C 调用 C++ 函数

//xx.h
extern "C"{
    int add();
}
//xx.cpp
int add(){
    
}
//xx.c
extern int add();

不过与 C++ 调用 C 接口不同,C++ 确实是能够调用编译好的 C 函数,而这里 C 调用 C++,不过是把 C++ 代码当成 C 代码编译后调用而已。也就是说,C 并不能直接调用 C++ 库函数。

PDF:链接 密码:5ve0

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值