extern "C"的含义是编译生成的内部符号名使用C语言的规则。我们需要知道的是,对于不同的编译器,在编译一个函数时,编译出来的函数名称或参数排列的顺序可能是不同的。例如,我们假设某个函数的原型为:void foo( int x, int y ); 该函数被C编译器编译后在符号库中的名字可能为_foo,而C++编译器则会产生像_foo_int_int之类的名字(_foo_int_int这样的名字包含了函数名、函数参数数量及类型信息,C++就是靠这种机制来实现函数重载的)。那么当我们用一种语言去调用另一种语言函数的时候,,需要告诉编译器去执行不同的编译器调用规则。
extern "C"告诉编译器用C语言的规则去编译调用函数(extern "FORTRAN"告诉编译器用FORTRAN语言的规则去编译调用函数)。extern "C"使用最多的地方是在C++语言中调用自定义C库的函数。将C定义的函数用extern "C"声明,以确保C++程序中调用的C函数是用C语言的规则进行编译的,而不是用C++语言规则编译的。下面举几个简单例子。
1 C++引用C中的函数
基本的步骤只有三步:
1)在C文件中定义被调用函数;
2)在CPP文件中使用extern "C"声明该函数;
3)在CPP文件中调用该函数。
代码如下:
//hello.c文件 实现hello函数
#incl? <stdio.h>
void hello()
{
printf("Hello,C!\n");
}
//main.cpp文件 调用hello函数
#incl? <iostream>
using namespace std;
extern "C"
{
void hello();
};
int main()
{
hello();
return 0;
}
需要说明的是,如果在hello.c文件中加入了extern "C"的话,会出现错误,提示的错误信息是error C2059: syntax error : 'string'。出现这个错误的原因是extern "C"是C++中的关键词,C不支持。还有就是如果去掉了main.cpp中的extern "C"的话,提示的错误信息如下:
Error 1 error LNK2019: unresolved external symbol "void __cdecl hello(void)" (?hello@@YAXXZ) referenced in function _main E:\user\Documents\Vis l St io 2010\Projects\test2010\test2010\main.obj
2 C引用C++中的函数
基本步骤如下:
1)在CPP文件中使用extern "C"定义被调用函数;
2)在C文件中声明该函数;
3)在C中调用该函数。
代码如下:
//main.cpp文件 使用extern "C"定义hello函数
#incl? <iostream>
using namespace std;
extern "C"
{
void hello()
{
cout<<"Hello,C++!"<<endl;
}
}
//hello.c文件 调用main.cpp中定义的函数
#incl? <stdio.h>
void hello();
int main()
{
hello();
return 0;
}
如果去掉main.cpp文件中的extern "C",会提示如下错误:
Error 1 error LNK2019: unresolved external symbol _hello referenced in function _main E:\user\Documents\Vis l St io 2010\Projects\test2010\test2010\hello.obj
hello.c文件没有定义hello函数,而main.cpp文件中定义的hello函数编译后的名称为"void __cdecl hello(void)" (?hello@@YAXXZ),而不是_hello,所以会出现上面的错误信息。
3 根据不同情况选择不同的代码
总像上面那样写代码,感觉的确不爽,如何能够根据不同的情况选择不同的代码呢?一个办法就是创建一个C与C++可以共用的头文件。具体代码如下:
//hello.h#ifdef __cplusplus#incl? <iostream>using namespace std;extern "C"{#endifvoid hello();#ifdef __cplusplus}#endif
__cplusplus表示使用的语言是C++,一个默认的宏定义。这个头文件比较好理解吧,如果程序是用C++语言写的,那么包括<iostream>,并使用标准命名空间。这样的写法不管是用C写的程序,还是C++写的程序,这个头文件都可以正常使用。举个例子,我们使用C++语言完成hello()函数,使用C语言调用。代码如下:
//hello.cpp#incl? "hello.h"void hello(){cout << "Hello, C++!" << endl;}//main.c#incl? "hello.h"int main(){hello();return 0;}
程序显示的结果是
怎么样,说明__cplusplus起作用了。大家尝试借助这个头文件,利用C语言实现hello()函数,使用C++语言调用,我就不再这里赘言啦!