C和C++之用extern "C"实现它们之间的互调

来源:互联网 发布:营销软件知乎 编辑:程序博客网 时间:2024/06/03 18:20

1、extern "C"的解释


    一个C++程序包含其它语言编写的部分代码。C++编写的代码片段可能被使用在其它语言编写的代码中,不同语言编写的代码互相调用是困难的,甚至是同一种编写的代码但不同的编译器编译的代码。例如,不同语言和同种语言的不同实现可能会在注册变量保持参数和参数在栈上的布局,这个方面不一样。

    为了使它们遵守统一规则,可以使用extern指定一个编译和连接规约。例如,声明C和C++标准库函数strcyp(),并指定它应该根据C的编译和连接规约来链接:

    extern "C" char* strcpy(char*,const char*);

    注意它与下面的声明的不同之处:
        
    extern char* strcpy(char*,const char*);

    下面的这个声明仅表示在连接的时候调用strcpy()。

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

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

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

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



2、小结extern "C"


    我们知道extern "C"的真实目的是实现类C和C++的混合编程。在C++源文件中的语句前面加上extern "C",表明它按照类C的编译和连接规约来编译和连接,而不是C++的编译的连接规约。这样在类C的代码中就可以调用C++的函数or变量等。(注:我在这里所说的类C,代表的是跟C语言的编译和连接方式一致的所有语言)



3、C和C++互相调用


    我们既然知道extern "C"是实现的类C和C++的混合编程。下面我们就分别介绍如何在C++中调用C的代码、C中调用C++的代码。首先要明白C和C++互相调用,你得知道它们之间的编译和连接差异,及如何利用extern "C"来实现相互调用。
    
    

4、C++的编译和连接


    C++是一个面向对象语言(虽不是纯粹的面向对象语言),它支持函数的重载,重载这个特性给我们带来了很大的便利。为了支持函数重载的这个特性,C++编译器实际上将下面这些重载函数:

    void print(int i);    void print(char c);    void print(float f);    void print(char* s);
    编译为:
            _print_int    _print_char    _print_float    _pirnt_string



    这样的函数名,来唯一标识每个函数。注:不同的编译器实现可能不一样,但是都是利用这种机制。所以当连接是调用print(3)时,它会去查找_print_int(3)这样的函数。下面说个题外话,正是因为这点,重载被认为不是多态,多态是运行时动态绑定(“一种接口多种实现”),如果硬要认为重载是多态,它顶多是编译时“多态”。

    C++中的变量,编译也类似,如全局变量可能编译g_xx,类变量编译为c_xx等。连接是也是按照这种机制去查找相应的变量。



5、C的编译和连接



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



6、C调用C++文件的函数例子


cppHead.h文件
//// Created by chenyu on 6/6/17.//#ifndef HELLO_CPPHEAD_H#define HELLO_CPPHEAD_Hextern "C" void showData(int i);#endif //HELLO_CPPHEAD_H



cppHead.cpp文件

//// Created by chenyu on 6/6/17.//#include "cppHead.h"#include <iostream>using namespace std;extern "C" void showData(int i){    std::cout<<"i is " << i << std::endl;}



main.c文件
//// Created by chenyu on 6/6/17.////#include <stdio.h>extern void showData(int i);int main(){    showData(5);}


7、结果展示



8、C++调用C文件的函数

cHead.h文件

extern void show(int i);

cHead.c文件

//// Created by chenyu on 6/6/17.//#include <stdio.h>#include "cHead.h"void show(int i){    printf("i is %d\n", i);}

main.cpp文件

#include <iostream>extern "C" {    #include "cHead.h"}int main() {    show(10);    return 0;}


9、结果展示

  

   

原创粉丝点击