详细介绍:extern “C”关键字
extern “C”
在C++中,**extern“C”**关键字用于指示编译器按照C语言的方式来处理被修饰的代码。这意味着被修饰的函数或变量将不会进行C++的名称修饰(name mangling),从而使得C++代码可以调用C语言的函数或变量。
例如,假设我们有一个C语言的库文件math.c,其中定义了一些数学函数:
// math.c文件
int add (int x,int y)//加法
{return x+y;
}
int sub(int x,int y)//减法
{return x-y;
}
int mult(int x,int y)//乘法
{return x*y;
}
int div(int x,int y) //除法
{return x/y;
}
在C++文件中,我们可以使用**extern“C”来声明这些函数,从而在C++代码中调用它们:
// main.cpp文件
#include
using namespace std;
extern "C" {int add(int x, int y);int sub(int x, int y);
}
int main() {cout << add(10, 20) << endl; // 输出30cout << sub(10, 20) << endl; // 输出-10return 0;
}
在C++中,extern"C"修饰的语句是按照C语言的方式进行编译的。
怎么理解这句话呢?
我来举几个例子:(理解它extern"C"的含义)
我们知道在C++中函数是可以发生重载的,即编译的时候并不会报错,在C语言中,是没有重载的说法的;那么假如我用extern"C"去修饰重载的函数的话,即在编译时候,就会按照C语言的方式去编译了:
这个时候,就会发生错误;
看例子:创建一个main.cpp文件
# include
using namespace std;
extern "C" void func() //用 extern"C"修饰
{
}
extern "C" void func(int v)//用 extern"C"修饰
{
{
}
int main()
{return 0;
}
这时会编译的时候会报错,不允许重载,本来使用C++文件就是可以重载的,但是用extern“C”修饰过后,就不可重载函数了,这就是按照C的编译方式编译,假如按C++编译方式编译那就是能通过的。
extern"C" 也是可以修饰声明函数的,也说明该函数时按照C语言的方式编译;
extern"C" 也是可以用大括号{ } 的方式声明函数的;
如下例子:
extern "C" void func(); //用 extern"C"修饰声明函数
extern "C" void func(int v);//用 extern"C"修饰声明函数
//上诉例子会报错,C语言编译没有重载啊。
///////////////////////////////
///////////////////////////////
///////////////////////////////
extern "C" { //修饰函数声明void func();void func(int v);
} //用大括号的方式一起写进来,也是可以。
//上诉例子会报错,C语言编译没有重载啊。
///////////////////////////////
///////////////////////////////
///////////////////////////////
extern "C" { //修饰函数定义void func(){}void func(int v){}
} //用大括号的方式一起写进来,也是可以。
//上诉例子会报错,C语言编译没有重载啊。
但是可以使用大括号的方式使用extern“C”,这是正确的
# include
using namespace std;
extern "C" void func() //用 extern"C"修饰
{
}void func(int v) //这个不用extern“C”声明{}
int main()
{return 0;
}
上面代码2的情况不会报错,原因很简单:extern "C" void func() { }
按C语言方式编译,这个不会错;void func(int v){ }
按C++方式编译,所以也不会报错,这两者虽然函数名字相同,但是他们时按照不同的编译方式编译的,所以不报错;
extern"C "使用 在C与C++混合开发中的使用方式
通常在C++ 中,假如需要使用C语言中的库文件的话,可以使用extern "C"去包含;
那如何使用呢?接下来我一步一步带你理解如何使用,先举几个例子。
比如:创建math.c(C文件)中,有一些函数是数学的加法和减法功能函数。
我想在main.cpp文件中使用math.c文件中的函数,如何使用呢?
第一种办法:在main.cpp文件用extern"C"包含math.c文件中的你想用的函数。
//math.c文件
int add (int x,int y)//加法
{return x+y;
}
int sub(int x,int y)//减法
{return x-y;
}
int mult(int x,int y)//乘法
{return x*y;
}
int div(int x,int y) //除法
{return x/y;
}
main.cpp(C++文件)中,要使用math.c文件中的函数.
//main.cpp文件
#include
using namespace std;
extern “C” //用extern“C”{ }声明math.c文件中的函数,以至于可以在main.cpp文件使用。
{int add (int x,int y);int sub(int x,int y);
}
int main()
{cout<
第二种使用方式:
// math.h文件的内容
int add (int x,int y);//加法
int sub(int x,int y);//减法
int mult(int x,int y);//乘法
int div(int x,int y); //除法
假如我有一个需求,我想在main.cpp文件,用math.c文件中的其他函数,比如除法函数,乘法函数;
那么我就只能在 main.cpp 中 extern"C"{ }的括号中,逐个的加上这两个函数;这好像也可以正常使用没问题,但是,这很麻烦啊,别人使用你的.c库时候会先得非常麻烦。所以我们一般使用头文件的方式,即创建多一个头文件math.h,在math.h里声明函数,在math.c文件定义函数,在main.cpp,即要使用该库文件里面,用extern"C"{ } ,在括号里包含该math.h头文件即可
看下math.h头文件内容:
在math.c中定义函数
//math.c文件
int add (int x,int y)//加法
{return x+y;
}
int sub(int x,int y)//减法
{return x-y;
}
int mult(int x,int y)//乘法
{return x*y;
}
int div(int x,int y) //除法
{return x/y;
}
这时候我们只要在main.cpp文件中,用extern “C”{ }包含该头文件就可以使用了。
//main.cpp文件
#include
using namespace std;
extern"C"{ //包含头文件,该里面是C语言方式编译的。# include"math.h"
}
int main()
{cout<
但是,上面的使用方式还是不太好,该方式还是有一定的问题,什么问题呢?就是我在main.cpp文件使用extern "C"{ #include"math.h"} ,即要多写一个 extern"C"{ },显得格外麻烦,再说了,假如还有其他Cpp文件要用这个C语言的库呢。都是这种方式,extern"C"太麻烦啦 。我们之前都是直接#include"math.h",这样才是我们平时的使用习惯呢。
所以有了这第三种使用方式:(为的是直接在main.cpp中,#include"math.h"就可以使用,不用多谢extern"C")
直接在math.h中,用extern"C"的方式修饰就行啦。那么我就可以在main.cpp直接#include"math.h"。
// math.h文件的内容
extern "C" {
int add (int x,int y);//加法
int sub(int x,int y);//减法
int mult(int x,int y);//乘法
int div(int x,int y); //除法
}
上面的使用有并不是完全好的方式,如何说呢?假如我有一个.c文件,创建为other.c,我这个文件呢,也想使用math.c的函数,那么我就可以在other.c文件直接包含该math.c文件就可以了,可是事实却不如所想,这样会报错,报错的原因是,由于在math.h文件中,声明函数用了extern"C",而other.c文件# include"math.h",会包含里面的所有内容,包括里面的 extern"C", 这个extern"C"在other.c文件,即C语言文件是不认识extern"C"啊,所以会报错
下面展示报错的代码,创建other.c
文件(C文件),里面包含math.h
文件(该文件有extern"C"{ }
声明方式 )
//other.c文件
# include"math.h"
//包含头文件,由于这是.c文件,不是.cpp文件。所以.c文件不认识extern"C",所以会报错
void test()
{int ret = add(10,20);//报错,不认识,add.
}
所以如何解决上面问题呢? 核心问题是,我希望有一种使用 extern"C"的方式,在C语言文件中,能够使用该库,在C++文件中也可以使用该库。
要解决这个问题:
也是 第四种使用方式
由于编译器默认会在,你创建的任何一个.cpp文件中,默认定义一个宏 #define __cplusplus,这个宏是你看不到的,是编译器默认给每个.cpp文件创建的,而在.c文件,即C语言的编译器,是没有这个宏的,所以我们可以借助它,来在 math.h文件中使用下面的代码:
看math.h的代码
// math.h文件的内容
//意思是如果使用该头文件math.h的文件定义了__cplusplus,
//则下面代码到#endif都是有效的,在这里是 extern "C" { 有效
#ifdef __cplusplus
extern "C" {
#endif //__cplusplus
int add (int x,int y);//加法
int sub(int x,int y);//减法
int mult(int x,int y);//乘法
int div(int x,int y); //除法
//意思是如果使用该头文件math.h的文件定义了__cplusplus,
//则下面代码到#endif都是有效的,在这里是 } 有效
#ifdef __cplusplus
}
#endif //__cplusplus
只要按上面的方式书写,那么就可以完美的解决了在C文件和C++文件中混用的问题;你既可以在.c文件使用该头文件,也可以在.cpp文件中使用该文件库。
第四种方式是最值得推荐的。