微尘--KeepMoving

为了忘却的记忆
posts - 3, comments - 2, trackbacks - 0, articles - 13
  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

也谈 extern "C" 的用法

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》
        

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理