extern C

extern “C”

extern "C"的作用

被extern “C“修饰的代码会按照C语言的方式去编译。声明需要使用extern C,实现不需要。

如果extern C加在实现上,会出现链接方式的冲突问题。

extern "C"{

void dosomething();
int getIndex();

const char* getName();
}

void dosomething()
{
    
}

int getIndex()
{
    
}
const char* getName()
{
    
}

首先,C++是支持函数重载的, c语言不支持

//function.cpp---编译通过
void func()
{...}

void func(int var)
{...}


//function.c----编译不通过
void func()
{...}

void func(int var)
{...}

例如上面两个函数,编译器知晓这是C++源文件,支持函数的重载。所以能够编译的过去,那么如果我用extern "C"去修饰,会有什么结果?

//function.cpp---编译通过
extern "C" void func()
{...}

extern "C" void func(int var)
{...}

//或者
extern "C"{
    void func(){...}
    void func(int var){...}
}

使用vs2017的编译环境。。编译后,ide给出的错误提示是:

  • error C2733: 不允许重载函数“func”的第二个C链接。

当使用extern C修饰的时候,函数会被编译器按照C语言的方式去编译。但是由于C语言是不支持函数重载的,这就意味着第二个函数是不会许可的。

按照编译器生成的的函数标签

//如果是C语言函数
void func()->可能的函数标签就是func
//如果是C++函数,由于C++支持函数重载
void func()->func_void_emtpy_var
void func(int var)->func_void_int_var

可以看到,编译器对C语言的函数和C++的函数生成的函数标签不一样。

什么时候用到extern C

我们在项目开发中,遇到第三方的库,第三方库可能是用C语言编写的,给我们的接口就是C语言函数接口,比如mysql的库等

举例:

//mymath.c
int sum(int a, int b)
{
    return a + b;
}
//main.cpp
#include <iostream>

using namespace std;

//使用extern "C"修饰
extern "C"
{
    int sum(int a, int b);
}

int main()
{
	int res = sum(3, 2);
	std::cout << "res = " << res << std::endl;
	return 0;
}

上面例子中,使用extern C修饰了sum函数。如果不用,C++会认为这是一个C++函数,函数签名很大可能会变成sum_int_int,而在mymath.c中只有sum这个签名,所以会导致一个大家很常见的连接错误:"无法解析的外部符号

int _cdecl sum(int, int);该函数在main.cpp中被引用"。使用extern C修饰后,签名一致,能够找到函数了,链接也通过。

当我们写C语言函数接口给别人使用
//一个很简单的例子
//mymath.h

//第二种办法,使用CPLUSPLUS宏定义处理extern C
#ifdef __cplusplus
extern "C"
{
#endif
int sum(int a, int b);
int del(int a, int b);
#ifdef __cplusplus
}
#endif

//mymath.c
int sum(int a, int b)
{
    ...
}

int del(int a, int b)
{
    ...
}
#include <iostream>

//第一种方法,不处理mymath.h的头文件,直接extern “c”包含进来
extern "C"{
    #include "mymath.h"
}

//第二种办法--符合常理
#include "mymath.h"

int main()
{
    int ret = sum(3, 2);
    return 0;
}

解释一下第二种办法:如果按照第一种办法,好处不需要对mymath.h的头文件做任何处理。cpp文件,c文件都可以调用mymath.h的功能。但是一般来说,这个处理的比较少。所以第二种办法使用的比较多。对于调用者,我们直接#include “header file”即可,库提供者或者源码提供者自己做处理。

当cpp调用mymath头文件,我们使用extern “C”修饰。当C语言调用该头文件,由于extern “C”属于c++编译环境下的产物,会导致编译不过去,不能识别extern C。那么由于对于cpp文件,编译器会给该文件自动添加一个宏__cplusplus来标明是cpp,所以我们利用这个宏,可以做到一个开关作用,用这个宏来修饰extern “C”。让它对不同的编译环境起到不同的作用,使得C和C++调用均可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值