zoukankan      html  css  js  c++  java
  • C与C++接口相互调用

    转载于:http://blog.csdn.net/lincoln_2012/article/details/50801080   

      项目中经常使用C和C++混合编程,那么,在调用对方接口时,总是不可避免地出现问题。为了让双方和谐地工作,就得用到extern "C"。

    1 问题

        在C++中,为了支持重载机制,在编译时,要对函数的名字进行一些处理,比如加入函数的返回类型等来加以区别;在C中,只是简单的函数名字而已。如函数void func(int i),C++会把它编译成类似_fun_int或_xxx_funIxxx这样的增加了参数类型的符号,这也是C++可以实现重载的原因;C则把该函数编译成类似_fun的符号,C链接器只要找到该函数符号就可以链接成功,它假设参数类型信息是正确的。故而,关键问题是,C和C++在编译时生成函数名字的方式是不同的。

    2 方法

        extern "C"是C++的特性,是一种链接约定,它并不影响调用函数的定义,即使做了该声明,对函数类型的检查和参数转换仍要遵循C++的标准,而不是C。主要是为了解决C++在调用C函数库时,用C++直接链接就会出现不能识别符号的问题,而用上extern "C"后,告诉C++编译器要以C语言的方式编译和链接函数,即直接使用函数名而不是一个经过处理的函数名。

    3 示例

    3.1 C++中调用C接口

    代码:

    1. /***** C头文件c.h *****/  
    2. #ifndef  _C_H_  
    3. #define _C_H_  
    4.   
    5. #ifdef __cplusplus    /*C++编译器包含的宏,例如用g++编译时,该宏就存在,则下面的语句extern "C"才会被执行*/  
    6. extern "C" {          /*C++编译器才能支持,C编译器不支持*/  
    7. #endif  
    8.   
    9. void C_fun();  
    10.   
    11. #ifdef __cplusplus  
    12. }  
    13. #endif  
    14.   
    15. #endif  
    1. /***** C源文件c.c *****/  
    2. #include "c.h"  
    3. void C_fun()  
    4. {  
    5.     /*dosomething*/  
    6. }  
    1. 功能:在文件cpp.cpp中调用文件c.c中的函数C_fun()  
    2. /****** C++源文件cpp.cpp ******/  
    3. #include "c.h"  
    4. int main()  
    5. {  
    6.      C_fun()  
    7. }  

    编译: g++ cpp.cpp c.c

    3.2 C中调用C++接口

    代码:

    1. /**** C++头文件 cpp.h *****/  
    2. #ifndef  CPP_H  
    3. #define CPP_H  
    4.   
    5. extern "C" int add( int x, int y );  
    6.   
    7. #endif  
    1. /**** C++源文件 cpp.cpp *****/  
    2. #include "cpp.h"  
    3. int add( int x, int y )  
    4. {  
    5.     return x + y;  
    6. }  
    1. 功能:C文件中调用C++的接口  
    2. /**** C源文件c.c *****/  
    3. extern int add( int x, int y );  
    4. int main( int argc, char* argv[])  
    5. {  
    6.       
    7. }  

    编译:gcc c.c cpp.cpp

    3.3 C++中调用C库的函数

    代码:

    1. /*C库源文件: hello.c*/  
    2. #include <stdio.h>  
    3. void func()  
    4. {  
    5.     printf("hello,world! ");  
    6. }  

    编译:gcc --shared -o libhello.so hello.c

    1. /*C++源文件test.cpp中调用C库的函数*/  
    2. #include <iostream>  
    3.   
    4. #ifdef __cplusplus  
    5. extern "C" {               // 告诉编译器下列代码要以C链接约定的模式进行链接  
    6. #endif  
    7.   
    8. void func();  
    9.   
    10. #ifdef __cplusplus  
    11. }  
    12. #endif  
    13.   
    14. int main()  
    15. {  
    16.     func();  
    17.   
    18.     return 0;  
    19. }  

    编译:g++ test.cpp -o test -lhello

    3.4 C中调用C++库的函数

    1)C++库代码

    1. /*C++库源文件hello.cpp*/  
    2. #include <iostream>  
    3.   
    4. void funcpp()  
    5. {  
    6.   std::cout << "hello, world" << std::endl;  
    7. }  

    编译:g++ --shared -o libhello.so hello.cpp
    2)中间接口库,对C++库进行二次封装

    1. /*中间接口库 mid.cpp*/  
    2. #include <iostream>  
    3.   
    4. void funcpp();  
    5.   
    6. #ifdef __cplusplus  
    7. extern "C" {  // 即使这是一个C++程序,下列这个函数的实现也要以C约定的风格来搞!  
    8. #endif  
    9.   
    10. void m_funcpp()  
    11. {  
    12.     funcpp();  
    13. }  
    14.   
    15. #ifdef __cplusplus  
    16. }  
    17. #endi  

    编译:g++ --shared -o libmid.so mid.cpp -lhello
    3)C通过链接二次接口库调用C++库

    1. /*C源文件test.c*/  
    2. #include <stdio.h>  
    3.   
    4. int main()  
    5. {  
    6.     m_funcpp();  
    7.   
    8.     return 0;  
    9. }  

    编译:gcc test.c -l mid -o test

  • 相关阅读:
    外观模式
    享元模式
    c#中的抽象类和接口
    装饰者模式
    组合模式
    适配器模式
    springboot 源码篇002## web层自动装配部分源码
    springboot 源码篇002## 自动装配原理
    springboot 源码篇 01
    shell 脚本基础 第二篇
  • 原文地址:https://www.cnblogs.com/feige1314/p/7890982.html
Copyright © 2011-2022 走看看