Posted on 2008-02-25 20:46
微尘 阅读(530)
评论(0) 编辑 收藏 引用 所属分类:
Windows编程
相信大家在编码中,有时会见到某某函数前面加了 extern "C" 的关键字修饰,尤其在模块(Dll)提供的头文件中。但是否很清楚的了解它的作用, 我当时第一次碰到时,其实是懂非懂的^_^。查了些资料,才明白其用法,详细如下。
1. 首先说下编译器编译函数时,对函数名的处理。
在C语言中,对函数如: IRoleView* RoleViewCreate(int nType); 编译后生成的函数名是RoleViewCreate
但是在C++中,由于存在函数重载的特性,所以编译时C++编译器会根据参数、返回值等信息对函数名改编,如上面函数在C++编译器中生成的函数名是
?RoleViewCreate@@YAPAVIRoleView@@H@z 2. extern "C"的含义。
extern "C" 有两重含义:
其一,被修饰的变量或函数是extern的存储类型,它告诉编译器,其声明的变量或函数可以被本模块和外部某块使用。
其二,被其修饰的函数或变量是按照C语言的方式来编译和链接的。
注意,extern "C"写法 只在C++中被支持,C语言不支持该写法。
3. extern "C"的两种惯用用法:
a) 在C++中使用C语言的函数或变量,在包含C语言提供的头文件是,需要用 extern "C" { } 来包含头文件。如下:
extern "C"
{
#include "lua.h" //lua.h是C编写,并提供的头文件
}
这里引用下第1点的函数来说明上述写法的用途:假设lua.h中包含函数 IRoleView* RoleViewCreate(int nType), 那么C语言的编译时生成的函数名是RoleViewCreate,而当C++客户程序去使用它时,默认是按C++的链接方式(即不加以上的 extern "C"时),所以C++客户程序会去外部模块中查找函数名为
?RoleViewCreate@@YAPAVIRoleView@@H@z的函数,这样C++编译器会找不到该函数,报出"无法解析的外部标识符"的错误; 而当加上
extern "C" { } 时,它就告诉编译器头文件中包含的函数或变量要按照C语言的编译链接方式进行,所以C++编译器会去外部模块查找函数名为
RoleViewCreate的函数,从而得到正确结果。
b) 在C中调用一个C++语言中的函数或变量时,C++的头文件需要添加 extern "C",这是为了让编译器对函数或变量按C语言的方式进行编译,已供C语言调用; 但在C语言中,不能直接包含声明了extern "C"的头文件,而应该在C文件中把在C++头文件中定义的函数,声明为 extern类型,因为在C语言中,并不支持extern "C"的写法;
参考资料:《C++中extern "C" 含义深层探索》作者:宋宝华
《C++ Primer》