转载于: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接口

代码:

[cpp] view plain copy
  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
[cpp] view plain copy
  1. /***** C源文件c.c *****/
  2. #include "c.h"
  3. void C_fun()
  4. {
  5. /*dosomething*/
  6. }
[cpp] view plain copy
  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++接口

代码:

[cpp] view plain copy
  1. /**** C++头文件 cpp.h *****/
  2. #ifndef  CPP_H
  3. #define CPP_H
  4. extern "C" int add( int x, int y );
  5. #endif
[cpp] view plain copy
  1. /**** C++源文件 cpp.cpp *****/
  2. #include "cpp.h"
  3. int add( int x, int y )
  4. {
  5. return x + y;
  6. }
[cpp] view plain copy
  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库的函数

代码:

[cpp] view plain copy
  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

[cpp] view plain copy
  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++库代码

[cpp] view plain copy
  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++库进行二次封装

[cpp] view plain copy
  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++库

[cpp] view plain copy
  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

转载于:https://www.cnblogs.com/feige1314/p/7890982.html

C与C++接口相互调用相关推荐

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

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

  2. android js接口调用方法,详解Android JS相互调用

    最近在研究Android.JS相互调用,之前没怎么接触过,只知道loadUrl()就可以加载一个网页了,研究过之后发现Android可以调JS,JS也可以调Android原生控件,很开心啊.下面小编就 ...

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

    1.首先先看什么是Feign. 2.若其他服务的接口未做权限处理,参照上文第1点的博文即可. 3.若其他服务的接口做了权限的处理(例如OAuth 2)时该如何访问? a.有做权限处理的服务接口直接调用 ...

  4. java与js交互,相互调用传参

    随着前端技术的发展与H5的广泛使用,移动端采用native+h5的方式越来越多了,对于Android来说就涉及到java与js的交互,相互调用传参等.下面就来看一下java与js交互的简单demo. ...

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

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

  6. Python与C之间的相互调用

    Python与C之间的相互调用(Python C API及Python ctypes库) 分类: [Python]2010-01-24 17:58 32468人阅读 评论(11) 收藏 举报 pyth ...

  7. C++和C#相互调用COM组件的方法简介

     1.在VS2005中,C#编写DLL并使用C++调用 2.在VS2005中C#编写的COM组件,使用VC6.0调用 3.在VC6.0中编写COM组件,使用VS2005 C#调用 4.在VC6.0 ...

  8. swift 打包sdk_在封装SDK中Swift和OC混编之相互调用

    oc和swift混编之相互调用.jpg 在非SDK中: 1.swift调用oc 步骤: 创建 工程名-Bridging-Header.h 放入oc的头文件,swift即可调用 在swift项目中或者在 ...

  9. Android JNI学习(五)——Java与Native之间如何实现相互调用

    本章将讲述Java与Native之间如何实现相互调用.我将围绕围绕如下三点来讲解. #mermaid-svg-qeVnGlVrLWrB5ryX .label{font-family:'trebuche ...

  10. unity 热更新:C#与Lua相互调用(转载)

    一.基本原理 简单地说,c#调用lua, 是c# 通过Pinvoke方式调用了lua的dll(一个C库),然后这个dll执行了lua脚本. ULua = Lua + LuaJit(解析器.解释器) + ...

最新文章

  1. OWA登录页面显示为英文而不是中文
  2. VTK 7.0 安装中内存读取冲突 no override found for “.. 解决记录
  3. 使用EventViewer记录VSTO add-in启动错误
  4. 气温常年在25度的地方_最低调的海滨城市,物价便宜,常年25度,沙滩细白,不输三亚!...
  5. python 太灵活_Python中的灵活参数
  6. python中numpy.transpose()函数详解
  7. 基于8086的中断方式4*4矩阵键盘
  8. Hutool介绍(详)
  9. java在线测试工具_9个最好用的在线编译/调试工具
  10. 无刷电机工作及控制原理
  11. 如何在excel单元格中插入图片批注
  12. Sp是如何走到这一步
  13. 谷歌2022学术指标出炉!Nature继续霸榜,CVPR第4,计算机5顶会入Top20
  14. 图片和文字对齐的方法
  15. linux 8g内存只认4g,为什么8g运行内存只有4g可用
  16. PHP模式-单例模式
  17. 深入学习Java:关于List下标越界源码分析
  18. 网页头部的声明 lang=zh和 lang=zh-cn 及 lang=zh-cmn的区别
  19. jdbc之oracle
  20. 关于dpi、dp与sp的基础了解

热门文章

  1. 获取用户真实IP以及internalProxies
  2. k8s学习笔记-环境搭建篇
  3. mac修改文件的默认打开方式
  4. ensure函数_vue按需加载组件webpack require.ensure的方法
  5. 血汗泪计算机音乐,血汗泪 - pikaCinDy_ - 5SING中国原创音乐基地
  6. 苹果cms模板_我的主题网【第二十五套】精简宽屏大气苹果CMSv10模板DIY系列拆分版...
  7. 【渝粤教育】广东开放大学 民族音乐概论 形成性考核 (58)
  8. Building libmesh with Petsc support
  9. c编程技巧——获取可用的处理器(CPU)核数
  10. PageHelpe的分页不起作用