zoukankan      html  css  js  c++  java
  • extern "C"

    经常看到如下代码:

    #ifdef _cplusplus

    extern "C" {

    #endif

    #include "XXX.h"

    #ifdef _cplusplus

    }

    #endif

    解释:

    extern "C"的作用是,告诉C++编译器,下面的代码按照C的方式进行编译,说白了,不要对这些函数进行名字重整(function name mangling)。通常在C++程序中使用C函数或者模块时,需要用到这个功能。

    原因:

    C++为了支持函数重载,将编译后的函数名做了重整(mangled name),比如下面的函数

    int add(int a, int b) ;

    在C中编译完的名字就是add,而在C++中,编译完就变成了add_int_int(举例而已,实际因编译器而异),这样在函数名字后面加上参数的类型,就可以区分不同的重载函数了,比如还有另一个函数

    float add(float a, float b) ;

    在C++中,它会被编译成add_float_float,这就是C++区分重载函数的机制

    可是问题也随之而来

    C++进行名字重整,而C不进行重整。当C++程序引用C的函数时,它会按照重整后的名字去目标文件(.obj)中去寻找对应的函数,而目标文件中存放的却是C版本的函数,名字对不上,所以根本找不到!

    怎么办呢?

    这就是extern “C” 存在的一个原因了

    它告诉C++,包含在extern “C”{ //…}块中的东西是C版本的,你编译的时候不要进行名字重整,否则你链接的时候就无法找到我!

    于是上面的代码也就不难理解了,光说不练是扯淡,上代码

    我们简单的定义一个C头文件和实现文件,只包含一个add函数

    CClass.h 内容如下

    #ifndef __CClass_H__

    #define __CClass_H__

    extern int add(int a, int b) ;

    #endif // end __CClass_H__

    CClass.c 内容如下

    #include "CClass.h"

    int add(int a, int b)

    {

    return a + b ;

    }

    下面我们用一个C++程序来引用这个C文件

    main.cpp 内容如下

    #define _cplusplus // 为了测试,强加一句

    #ifdef _cplusplus

    extern "C" {

    #endif

    #include "CClass.h"

    #ifdef _cplusplus

    }

    #endif

    #include <iostream>

    using namespace std ;

    int main(void)

    {

    int result = add(1, 2) ;

    cout << result << endl ;

    system("pause") ;

    return 0 ;

    }

    如果没有#include <iostream>之前那些代码而只是仅仅包含

    #include "CClass.h"一句

    你就会得到下面的错误

    error LNK2019:unresolved external symbol "int __cdecl add(int,int)" (?add@@YAHHH@Z) referenced in function _main

    显然这是一个链接错误,因为找不到对应的函数定义

    当然你也可以简写成下面的形式,直接在extern “C”块中包含你想调用的函数

    extern "C"

    {

    int add(int a, int b) ;

    };

    #include <iostream>

    using namespace std ;

    int main(void)

    {

    int result = add(1, 2) ;

    cout << result << endl ;

    system("pause") ;

    return 0 ;

    }

    这在C++程序中是没有问题的,但是如果是在C程序中,则会出现编译错误,因为C中不允许extern “C”出现

    另一个需要extern “C”的场合是当C程序调用C++的东西时

    按照如下步骤做即可

    1. 在C++的.h文件中用extern “C”{}声明将被C程序使用的函数

    2. 在C++的.cpp文件中实现上面的函数

    3. 在.c文件中用extern声明要使用的C++函数

    4. 使用即可

    注意:切不可在.c文件中包含C++的.h文件,那样编译无法通过

    上代码:

    CPPClass.h中声明add函数

    #ifndef __CPPClass_H__

    #define __CPPClass_H__

    extern "C"

    {

    int add(int a, int b) ;

    };

    #endif // end __CPPClass_H__

    CPPClass.cpp实现add函数

    #include "CPPClass.h"

    int add(int a, int b)

    {

    return a + b ;

    }

    main.c 内容如下

    #include <stdio.h>

    //#include "CPPClass.h" // 不要包含头文件,否则编译不过

    extern int add(int a, int b) ; // 只需显示声明要调用的函数即可

    int main(void)

    {

    int result = add(1, 2) ; //使用函数

    printf("%d", result) ;

    return 0 ;

    }

    作者:zdd
    出处:http://www.cnblogs.com/graphics/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.
  • 相关阅读:
    可重入的自旋锁
    自旋锁浅析
    hibernate规避SQL注入实例
    关于2B的转义问题
    java指定文件编码格式
    win10下启动zkui
    【转】角落的开发工具集之Vs(Visual Studio)2017插件推荐
    《LINQ技术详解C#》-4.延迟操作符(第2部分 LINQ到对象)
    《LINQ技术详解C#》-2.查询表达式翻译为标准查询操作符
    Code alignment 代码对齐改进(VS2017)
  • 原文地址:https://www.cnblogs.com/mrlsx/p/5994970.html
Copyright © 2011-2022 走看看