转载于: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. #ifdef __cplusplus    /*C++编译器包含的宏,例如用g++编译时,该宏就存在,则下面的语句extern "C"才会被执行*/
  5. extern "C" {          /*C++编译器才能支持,C编译器不支持*/
  6. #endif
  7. void C_fun();
  8. #ifdef __cplusplus
  9. }
  10. #endif
  11. #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. extern "C" int add( int x, int y );
  5. #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. }

编译: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!\n");
  6. }

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

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

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

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

1)C++库代码

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

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

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

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

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

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

C与C++接口相互调用的更多相关文章

  1. 【c++基础】C与C++接口相互调用

    前言 编译程序的时候出现错误,入口程序如果是cpp文件可以编译成功,如果是c程序则出错.一般这个问题是c与c++之间接口相互调用出现的问题. 出现的错误是undefined reference to ...

  2. .Net 与 Java 的服务接口相互调用

    本文介绍.Net 与 Java 相互调用的例子.下面的介绍主要包括三方面:一是通过常用Web服务进行相互调用,二是使用TCP/IP套接字进行相互调用,三是使用Remote实现远程对象相互调用. 首先说 ...

  3. spring cloud各个微服务之间如何相互调用(Feign、Feign带token访问服务接口)

    1.首先先看什么是Feign. 这里引用“大漠知秋”的博文https://blog.csdn.net/wo18237095579/article/details/83343915 2.若其他服务的接口 ...

  4. WebView中Js与Android本地函数的相互调用

    介绍 随着Html5的普及,html在表现力上不一定比原生应用差,并且有很强的扩展兼容性,所以越来越多的应用是采用Html与Android原生混合开发模式实现. 既然要实现混合开发,那么Js与Andr ...

  5. JAVA和C/C++之间的相互调用。

    在一些Android应用的开发中,需要通过JNI和 Android NDK工具实现JAVA和C/C++之间的相互调用. Java Native Interface (JNI)标准是java平台的一部分 ...

  6. Android中通过WebView控件实现与JavaScript方法相互调用的地图应用

    在Android中通过WebView控件,可以实现要加载的页面与Android方法相互调用,我们要实现WebView中的addJavascriptInterface方法,这样html才能调用andro ...

  7. JAVA与.NET的相互调用——通过Web服务实现相互调用

    JAVA与.NET是现今世界竞争激烈的两大开发媒体,两者语言有很多相似的地方.而在很多大型的开发项目里面,往往需要使用两种语言进行集成开发.而很多的开发人员都会偏向于其中一种语言,在使用集成开发的时候 ...

  8. JAVA与.NET的相互调用——利用JNBridge桥接模式实现远程通讯

    分布式开发的历史 利用Remote方式调用远程对象实现服务器与客户端之间通讯是一种常用的网络开发方式,在.NET与JAVA开发当中,对Remote远程对象早已有着足够的支持(对Remote远程对象调用 ...

  9. android与javascript相互调用

    下面这一节来介绍android和javascript是怎么相互调用的,这样我们的UI界面设计起来就简单多了,而且UI设计起来也可以跨平台.现在有好多web app前台框架了,比如sencha和jque ...

随机推荐

  1. WebApi迁移ASP.NET Core2.0

    WebApi迁移ASP.NET Core2.0 一步一步带你做WebApi迁移ASP.NET Core2.0   随着ASP.NET Core 2.0发布之后,原先运行在Windows IIS中的AS ...

  2. Net Core应用,在CentOS上运行

    Net Core应用,在CentOS上运行 本文主要介绍下运用docker虚拟技术打包Asp.net core应用. Docker作为一个开源的应用容器引擎,近几年得到广泛的应用,使用Docker我们 ...

  3. Ubuntu14.04 使用scp远程传输命令进行服务器文件互传

    1.将另一个服务器上的文件拷贝到本地 sudo scp host_name@host_ip:/home/aaa/bbb /ccc/ddd/bbb 上面命令的意思是将远程服务器/home/aaa/目录下 ...

  4. 天上掉馅饼 期望DP

    C 天上掉馅饼文件名 输入文件 输出文件 时间限制 空间限制bonus.pas/c/cpp bonus.in bonus.out 1s 128MB题目描述小 G 进入了一个神奇的世界,在这个世界,天上 ...

  5. swift3.0 项目引导页

    项目引导页并不难,使用 UICollectionView就可以完成, 1.首先获取应用程序的版本号,并存入本地,每次有新版本号,和存入本地的版本号,相比较 fileprivate func setup ...

  6. text-transform字母大小写属性设置

    text-transform: none: 默认  不设置,全是小写 capitalize: 每个单词以大写字母开头 uppercase: 全部是大写字母 lowercase:  全部是小写字母 in ...

  7. idea远程debug:tomcat

    在tomcat的bin/startup.sh中添加: 27780debug的端口 declare -x CATALINA_OPTS="-server -Xdebug -Xnoagent -D ...

  8. Android方法数methods超过65536

    当Android App中的方法数超过65535时,如果往下兼容到低版本设备时,就会报编译错误: Cannot fit requested classes in a single dex file. ...

  9. tomcat配置https 和 http强制跳转https

    https是http+ssl的可进行加密传输,身份认证的网络协议,防止数据在传输过程中被窃取.因此,https将得到越来越广泛的应用,下面是如何配置tomcat服务器让http自动转到https的步骤 ...

  10. BZOJ 2119: 股市的预测 SA

    2119: 股市的预测 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 434  Solved: 200[Submit][Status][Discuss ...