美文网首页我爱编程
深入理解C/C++混合编程

深入理解C/C++混合编程

作者: Joe_HUST | 来源:发表于2017-11-26 23:14 被阅读0次

    在实际的工作中,C、C++密不可分,做我们嵌入式方面的,当然更多的是C,但,有时候却少不了C++,而且是C、C++混搭(混合编程)在一起的,比如,RTP视频传输,live555多媒体播放等都是C++下的,他需要调用JRTPLIB库,再比如,邮件发送,我也用C++写的,定义了一个Email对象,包含了成员:收发邮件地址,用户名,密码等,以及方法:邮件头、Base64编码和邮件发送这些操作,很好用,所以,很多时候,C++还是蛮不错的。。。。但,.c与.cpp文件混搭在一起,不是那么的简单,我们就来慢慢的了解吧。

    C++之父在设计C++之时,考虑到当时已经存在了大量的C代码,为了支持原来的C代码和已经写好C库,需要在C++中尽可能的支持C,而extern "C"就是其中的一个策略。

    一 extern "C"的作用

    1. extern "C"的真实目的是实现类C和C++的混合编程。extern “C”是由C++提供的一个连接交换指定符号,用于告诉C++这段代码是C函数。extern “C”后面的函数不使用的C++的名字修饰,而是用C。这是因为C++编译后库中函数名会变得很长,与C生成的不一致,造成C++不能直接调用C函数。

    2. C++语言支持函数重载,C语言不支持函数重载。函数被C++编译后在库中的名字与C语言的不同。假设某个函数的原型为:void foo(int x, int y);该函数被C编译器编译后在库中的名字为_foo,而C++编译器则会产生像_foo_int_int之类的名字。C++提供了C连接交换指定符号extern“C”来解决名字匹配问题。

    3. 被extern "C"限定的函数或变量是extern类型的;extern是C/C++语言中表明函数和全局变量作用范围(可见性)的关键字,该关键字告诉编译器,其声明的函数和变量可以在本模块或其它模块中使用。被extern "C"修饰的变量和函数是按照C语言方式编译和连接的。

    4. 与extern对应的关键字是static,被它修饰的全局变量和函数只能在本模块中使用。因此,一个函数或变量只可能被本模块使用时,其不可能被extern “C”修饰。

    二 extern“C”与__cplusplus

    #ifdef __cplusplus
    extern "C" {
    #endif
    //....
    #ifdef __cplusplus
    }
    #endif
    

    __cplusplus是cpp中的自定义的宏,那么定义了这个宏的话表示这个文件是C++代码,也就是说,上面的代码的含义是:如果这是一段C++的代码,那么使用extern "C"来处理{ }之间的这段代码.即向C++编译器表明{ }之间的这段代码是C的代码.这是在C++的文件当中调用了C的代码.

    三 C调用C++函数(接口)

    若想在C中调用C++函数,则应该在C++的源文件中将这个函数声明为C风格的函数,即:

    //CPP文件
    extern "C" void f(void);
    
    void f(void)
    {
    /*somecode*/
    }
    
    

    但是这种方法仅仅适用于非成员函数,若我们想要在C当中调用成员函数(包括虚函数),则需要提供一个简单的包装(wrapper).例如:

    //C++ code
    class C{
    //...
    virtual double f(int);
    };
    
    extern "C" double call_C_f(C *p,int i) //wrapper function
    {
    return p->f(i);
    }
    

    然后,你可以这样调用C::f();

    //C code
    double call_C_f(struct C *p ,int i);
    void ccc(struct C *p,int i)
    {
    double = call_C_f(p,i);
    /*...*/
    }
    

    如果你想在 C 里调用重载函数,则必须提供不同名字的包装,这样才能被 C 代码调用。例如:

    // C++ code:
    void f(int);
    void f(double);
     
    extern "C" void f_i(int i) { f(i); }
    extern "C" void f_d(double d) { f(d); }
    

    然后,你可以这样使用每个重载的 f():

    /* C code: */
    void f_i(int);
    void f_d(double);
     
    void cccc(int i,double d)
    {
           f_i(i);
           f_d(d);
           /* ... */
    }
    

    相关文章

      网友评论

        本文标题:深入理解C/C++混合编程

        本文链接:https://www.haomeiwen.com/subject/woouuxtx.html