• extern "C"解析


    转自大牛的解析(非常具体详细)http://www.cnblogs.com/skynet/archive/2010/07/10/1774964.html

    我做个简单的标注方便以后自己查看:

    在用C++的项目源码中,经常会不可避免的会看到下面的代码:

    #ifdef __cplusplus  //采用c++,自动定义__cplusplus的宏
    extern "C" {
    #endif
     
    /*...*/
     
    #ifdef __cplusplus
    }
    #endif

    extern "C" 是为了实现C++与C及其它语言的混合编程,由于C++支持函数重载,同名函数在编译阶段会根据参数特征表的不同命名不同的全局名称,如:

    C++中  void func(int,int) 命名为 _func_int_int

    而C方式编译后命名为 _func

    3.2、C的编译和连接

    C语言中并没有重载和类这些特性,故并不像C++那样print(int i),会被编译为_print_int,而是直接编译为_print等。因此如果直接在C++中调用C的函数会失败,因为连接是调用C中的print(3)时,它会去找_print_int(3)。因此extern "C"的作用就体现出来了。

    3.3、C++中调用C的代码

    假设一个C的头文件cHeader.h中包含一个函数print(int i),函数前面的extern可加可不加,函数默认即为外部链接的(其他文件中声明引用也不需要要extern关键字,原作者这里有误)。它的代码如下:

    1 #ifndef C_HEADER
    2 #define C_HEADER
    3  
    4 extern void print(int i);
    5  
    6 #endif C_HEADER

    相对应的实现文件为cHeader.c的代码为:

    1 #include <stdio.h>
    2 #include "cHeader.h"
    3 void print(int i)
    4 {
    5     printf("cHeader %d
    ",i);
    6 }

    现在C++的代码文件C++.cpp中引用C中的print(int i)函数:

    1 extern "C"{  //即告诉编译器这里面是按C语言编译和链接的,调用这里的函数也按C的方式来进行
    2 #include "cHeader.h"
    3 }
    4  
    5 int main(int argc,char** argv)
    6 {
    7     print(3);
    8     return 0;
    9 }

    执行程序输出:

    image 

    3.4、C中调用C++的代码

    现在换成在C中调用C++的代码,这与在C++中调用C的代码有所不同。如下在cppHeader.h头文件中定义了下面的代码:

    1 #ifndef CPP_HEADER
    2 #define CPP_HEADER
    3  
    4 extern "C" void print(int i);
    5  
    6 #endif CPP_HEADER

    相应的实现文件cppHeader.cpp文件中代码如下:

    1 #include "cppHeader.h"
    2  
    3 #include <iostream>
    4 using namespace std;
    5 void print(int i)
    6 {
    7     cout<<"cppHeader "<<i<<endl;
    8 }

    在C的代码文件c.c中调用print函数:

    extern void print(int i);
    int main(int argc,char** argv)
    {
        print(3);
        return 0;
    }

    注意在C的代码文件中直接#include "cppHeader.h"头文件,编译出错。而且如果不加extern int print(int i)编译也会出错。

    extern "C"指令非常有用,因为C和C++的近亲关系。注意:extern "C"指令中的C,表示的一种编译和连接规约,而不是一种语言。C表示符合C语言的编译和连接规约的任何语言,如Fortran、assembler等。

    还有要说明的是,extern "C"指令仅指定编译和连接规约,但不影响语义。例如在函数声明中,指定了extern "C",仍然要遵守C++的类型检测、参数转换规则。

    再看下面的一个例子,为了声明一个变量而不是定义一个变量,你必须在声明时指定extern关键字,但是当你又加上了"C",它不会改变语义,但是会改变它的编译和连接方式。

    如果你有很多语言要加上extern "C",你可以将它们放到extern "C"{ }中。

    PS: extern 用于变量和函数

    之于变量

    player.h:

              //全局命名空间

              int a=20;//全局变量默认是extern的

             static int b=10;//定义内部链接的变量

    xxx.cpp:

              extern int a;// 只声明,不能重复定义

    之于函数

    函数默认都是外部链接的(如库文件定义的函数也都没有加extern关键字)

    player.h:

            void foo(){.....}

    xxx.cpp:

            #include "player.h";

             //包含头文件后,直接用就行了

  • 相关阅读:
    部署的influxdb没有可以web操作sql的页面
    JUnit5 @TestMethodOrder注释不起作用
    RestAssured 接口测试框架-环境搭建遇到的问题(1)
    PC前端代码 本地启动
    可有可无的“冒烟测试”
    adb devices 找不到连接设备 显示 List of devices attached 解决方法
    【转载】接口测试 rest-assured 使用指南(中文)
    工厂模式
    【腾讯云服务器】基于centos7搭建ftp服务器(vsftpd)
    centos下Django+uwsgi+nginx
  • 原文地址:https://www.cnblogs.com/fkissx/p/4695635.html
Copyright © 2020-2023  润新知