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接口
代码:
- /***** C头文件c.h *****/
- #ifndef _C_H_
- #define _C_H_
- #ifdef __cplusplus /*C++编译器包含的宏,例如用g++编译时,该宏就存在,则下面的语句extern "C"才会被执行*/
- extern "C" { /*C++编译器才能支持,C编译器不支持*/
- #endif
- void C_fun();
- #ifdef __cplusplus
- }
- #endif
- #endif
- /***** C源文件c.c *****/
- #include "c.h"
- void C_fun()
- {
- /*dosomething*/
- }
- 功能:在文件cpp.cpp中调用文件c.c中的函数C_fun()
- /****** C++源文件cpp.cpp ******/
- #include "c.h"
- int main()
- {
- C_fun()
- }
编译: g++ cpp.cpp c.c
3.2 C中调用C++接口
代码:
- /**** C++头文件 cpp.h *****/
- #ifndef CPP_H
- #define CPP_H
- extern "C" int add( int x, int y );
- #endif
- /**** C++源文件 cpp.cpp *****/
- #include "cpp.h"
- int add( int x, int y )
- {
- return x + y;
- }
- 功能:C文件中调用C++的接口
- /**** C源文件c.c *****/
- extern int add( int x, int y );
- int main( int argc, char* argv[])
- {
- }
编译:gcc c.c cpp.cpp
3.3 C++中调用C库的函数
代码:
- /*C库源文件: hello.c*/
- #include <stdio.h>
- void func()
- {
- printf("hello,world!\n");
- }
编译:gcc --shared -o libhello.so hello.c
- /*C++源文件test.cpp中调用C库的函数*/
- #include <iostream>
- #ifdef __cplusplus
- extern "C" { // 告诉编译器下列代码要以C链接约定的模式进行链接
- #endif
- void func();
- #ifdef __cplusplus
- }
- #endif
- int main()
- {
- func();
- return 0;
- }
编译:g++ test.cpp -o test -lhello
3.4 C中调用C++库的函数
1)C++库代码
- /*C++库源文件hello.cpp*/
- #include <iostream>
- void funcpp()
- {
- std::cout << "hello, world" << std::endl;
- }
编译:g++ --shared -o libhello.so hello.cpp
2)中间接口库,对C++库进行二次封装
- /*中间接口库 mid.cpp*/
- #include <iostream>
- void funcpp();
- #ifdef __cplusplus
- extern "C" { // 即使这是一个C++程序,下列这个函数的实现也要以C约定的风格来搞!
- #endif
- void m_funcpp()
- {
- funcpp();
- }
- #ifdef __cplusplus
- }
- #endi
编译:g++ --shared -o libmid.so mid.cpp -lhello
3)C通过链接二次接口库调用C++库
- /*C源文件test.c*/
- #include <stdio.h>
- int main()
- {
- m_funcpp();
- return 0;
- }
编译:gcc test.c -l mid -o test
C与C++接口相互调用的更多相关文章
- 【c++基础】C与C++接口相互调用
前言 编译程序的时候出现错误,入口程序如果是cpp文件可以编译成功,如果是c程序则出错.一般这个问题是c与c++之间接口相互调用出现的问题. 出现的错误是undefined reference to ...
- .Net 与 Java 的服务接口相互调用
本文介绍.Net 与 Java 相互调用的例子.下面的介绍主要包括三方面:一是通过常用Web服务进行相互调用,二是使用TCP/IP套接字进行相互调用,三是使用Remote实现远程对象相互调用. 首先说 ...
- spring cloud各个微服务之间如何相互调用(Feign、Feign带token访问服务接口)
1.首先先看什么是Feign. 这里引用“大漠知秋”的博文https://blog.csdn.net/wo18237095579/article/details/83343915 2.若其他服务的接口 ...
- WebView中Js与Android本地函数的相互调用
介绍 随着Html5的普及,html在表现力上不一定比原生应用差,并且有很强的扩展兼容性,所以越来越多的应用是采用Html与Android原生混合开发模式实现. 既然要实现混合开发,那么Js与Andr ...
- JAVA和C/C++之间的相互调用。
在一些Android应用的开发中,需要通过JNI和 Android NDK工具实现JAVA和C/C++之间的相互调用. Java Native Interface (JNI)标准是java平台的一部分 ...
- Android中通过WebView控件实现与JavaScript方法相互调用的地图应用
在Android中通过WebView控件,可以实现要加载的页面与Android方法相互调用,我们要实现WebView中的addJavascriptInterface方法,这样html才能调用andro ...
- JAVA与.NET的相互调用——通过Web服务实现相互调用
JAVA与.NET是现今世界竞争激烈的两大开发媒体,两者语言有很多相似的地方.而在很多大型的开发项目里面,往往需要使用两种语言进行集成开发.而很多的开发人员都会偏向于其中一种语言,在使用集成开发的时候 ...
- JAVA与.NET的相互调用——利用JNBridge桥接模式实现远程通讯
分布式开发的历史 利用Remote方式调用远程对象实现服务器与客户端之间通讯是一种常用的网络开发方式,在.NET与JAVA开发当中,对Remote远程对象早已有着足够的支持(对Remote远程对象调用 ...
- android与javascript相互调用
下面这一节来介绍android和javascript是怎么相互调用的,这样我们的UI界面设计起来就简单多了,而且UI设计起来也可以跨平台.现在有好多web app前台框架了,比如sencha和jque ...
随机推荐
- C#实现程序单例日志输出
对于一个完整的程序系统,一个日志记录是必不可少的.可以用它来记录程序在运行过程中的运行状态和报错信息.比如,那些不想通过弹框提示的错误,程序执行过程中捕获的异常等. 首先,在你的解决方案中,适当的目录 ...
- eclipse查看jar包源文件
话不多说上链接 https://www.cnblogs.com/1995hxt/p/5252098.html这里介绍了完整的流程,亲自试过,可以的! 以防以后要用的时候找不到文件的下载地址,所以就先在 ...
- ES5数组遍历
reduce() 方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值. array.reduce(function(total, currentValue, curren ...
- AJPFX关于Java中运用数组的四种排序方法
JAVA中在运用数组进行排序功能时,一般有四种方法:快速排序法.冒泡法.选择排序法.插入排序法.快速排序法主要是运用了Arrays中的一个方法Arrays.sort()实现.冒泡法是运用遍历数组进行比 ...
- JAVA常量介绍
常量: 在程序执行过程中,其值不发生改变的量: 1.分类: 字面值常量和自定义常量: 1.字面值常量有以下几种: 字符串常量.小数常量.整数常量.字符常量.布尔常量(true.false).空 ...
- PHP判断两个矩形是否相交
<?php $s = is_rect_intersect(1,2,1,2,4,5,0,3); var_dump($s); /* 如果两个矩形相交,那么矩形A B的中心点和矩形的边长是有一定关系的 ...
- HDU 4283 You Are the One (区间DP,经典)
题意: 某校举行一场非诚勿扰,给定一个出场序列,表示n个人的屌丝值,如果他是第k个出场的,他的不满意度为(k-1)*diao[i].为了让所有人的屌丝值之和更小,导演设置一个栈,可以将部分人装进栈中, ...
- POJ 3260 The Fewest Coins 最少硬币个数(完全背包+多重背包,混合型)
题意:FJ身上有各种硬币,但是要买m元的东西,想用最少的硬币个数去买,且找回的硬币数量也是最少(老板会按照最少的量自动找钱),即掏出的硬币和收到的硬币个数最少. 思路:老板会自动找钱,且按最少的找,硬 ...
- ASP.NET WebForm & MongoDB
ASP.NET WebForm & MongoDB 最近在朋友介绍下,也跟着看AngularJS 买了一本三合一的书,Node.JS+MongoDB+AngularJS http://www. ...
- Android(java)学习笔记135:SQLite数据库(表)的创建 以及 SQLite数据库的升级
一.数据库的创建 1.文件的创建 //引用,如果文件不存在是不会创建的 File file = new File("haha.txt"): //输出流写数据 ...