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 ...
随机推荐
- RabbitMQ使用教程(二)RabbitMQ用户管理,角色管理及权限设置
上一篇博客 RabbitMQ使用教程(一)RabbitMQ环境安装配置及Hello World示例 中,我们成功的安装好了RabbitMQ环境,并通过一个Java客户端示例了解了用生产者来发布消息,用 ...
- JDBC连接中Class.forName("")到底干了什么?
思考了一个问题,Class.forName("***");到底干了什么? 我们知道Class.forName( )静态方法的目的是为了动态加载类,但是一般来说,一个类forName ...
- 解决resteasy上传表单文件名乱码
Dubbo在2.6版本后合并了dubbox的resteasy代码后,可以支持rest风格的接口发布,但是在使用form表单上传文件的时候,获取的文件名称是乱码. 下面通过对源码分析一下原因,并提供一种 ...
- Linux下常用的数据恢复工具
一.数据删除 命令:rm -rf,将任何数据直接从硬盘删除,且没有任何提示 建议做法: 把命令参数放到后面:rm -rfi 将删除的东西通过mv命令移动到系统下的/temp目录下,然后写个脚 本定期执 ...
- GreenDao 数据库升级 连接多个DB文件 或者指定不同的model&dao目录
相信很多人都用过greenDao 今天 我抽空总结下使用的时候一些小东西吧 废话不多说 下边就GreenDao 的使用遇到的问题以及解决方案记录一下吧. 1.greendao 指定不同的生成目录: S ...
- servlet config
<webapp> <!--servlet是指编写的Servlet的路径,以及定义别名--> <servlet> <servlet-name>test&l ...
- 测试的发现遗漏BUG的做法
首先要确认BUG的影响范围: 后续做法如下: 1.从测试角度来说,外部缺陷等同与系统崩溃,测试是必须提的2.可以询问主管或负责人是否在后一个版本中修改3.评估缺陷对于用户使用存在多大的不便4.判定缺陷 ...
- userBean之设置属性
package com.java.model; public class Student { private String name;private int age; public String ge ...
- fpga Verilog hdl 按键消抖 部分程序讲解
module debounce(clk_in,rst_in,key_in,key_pulse,key_state); input clk_in;//system clock input rst_in; ...
- 将SQL2008升级为SQL2008 r2
我的SQL2008版本信息 Microsoft SQL Server Management Studio 10.0.1600.22 ((SQL_PreRelease).080709-1414 ...