C代码中如何调用C++ C++中如何调用C
注意这里的C调用C++或者C++调用C意思是.c文件中调用.cpp文件中代码,或者相反。
集成开发环境如VC++6.0或者vs都是以文件后缀来区别当前要编译的是C代码还是C++代码,然后采用响应的编译、调用协议等。
使用extern "C" 主要是因为C编译器编译函数时不带参数的类型信息,只包含函数的符号名字。如
int foo( float x )
C编译器会将此函数编译成类似_foo的符号,C连接器只要找到了调用函数的符号,就认为连接成功。
而C++编译器为了实现函数重载,会在编译时带上函数的参数信息。如它可以把上面的函数编译成类似于_foo_float这样的符号。
所以,C调用C++,使用extern "C"则是告诉编译器依照C的方式来编译封装接口,当然接口函数里面的C++语法还是按C++方式编译。
如:1 普通函数
// C++ Code
extern "C" int foo( int x );
int foo( int x )
{
//...
}
这样,编译器会将foo函数编译成类似_foo符号,而不会编译成类似_foo_int符号
则C可以这样调用C++函数
// C Code
int foo( int x );
void cc( int x )
{
foo( x );
//...
}
2 如果想调用重载的C++函数,则须封装单独的接口共C调用。
如
// C++ Code
void foo( int x );
void foo( float x );
extern "C" void foo_i( int x )
{
foo( x );
}
extern "C" void foo_f( float x )
{
foo( x );
}
则C中可这样调用
// C Code
void foo_i( int x );
void foo_f( float x );
void ccc( int x1, float x2 )
{
foo_i( x1 );
foo_f( x2 );
// ...
}
3 C中想调用C++中的成员函数(包括虚函数),则需要提供一个简单的包装(wrapper)。
例如: // C++ code:
class C
{
...
virtual double f(int);
};
extern "C" double call_C_f(C* p, int i) // wrapper function
{
return p->f(i);
}
然后,你就可以这样调用 C::f():
//C code
double call_C_f(struct C* p, int i);//声明
void ccc(struct C* p, int i)
{
double d=call_C_f(p,i);
...
}
问题:参数struct C* p从哪里来,即怎么在C中定义C++对象,其实上面只是说了思想,真实的c中使用C++类需要把原来的类都封装一下,参看下面的文章
http://blog.csdn.net/caspiansea/article/details/9676153
而C++调用C,extern "C" 的作用是:让C++连接器找调用函数的符号时采用C的方式 如:
// C Code
void foo( int x );
C++这样调用C函数
// C++ Code
extern "C" void foo( int x );
就是让C++连接器能过类似于_foo来查找此函数,而非类似于_foo_int这样的符号。
时常在cpp的代码之中看到这样的代码: 特别是C ++中引入C的头文件,这些C头文件中出现很多如下代码。
#ifdef __cplusplus extern "C" { #endif
//一段代码
#ifdef __cplusplus } #endif
要明白为何使用extern "C",还得从cpp中对函数的重载处理开始说起。在c++中,为了支持重载机制,在编译生成的汇编码中,要对函数的名字进行一些处理,加入比如函数的返回类型等等.而在C中,只是简单的函数名字而已,不会加入其他的信息.也就是说:C++和C对产生的函数名字的处理是不一样的.
明白了加入与不加入extern "C"之后对函数名称产生的影响,我们继续我们的讨论:为什么需要使用extern "C"呢?C++之父在设计C++之时,考虑到当时已经存在了大量的C代码,为了支持原来的C代码和已经写好C库,需要在C++中尽可能的支持C,而extern "C"就是其中的一个策略。
试想这样的情况:一个库文件已经用C写好了而且运行得很良好,这个时候我们需要使用这个库文件,但是我们需要使用C++来写这个新的代码。如果这个代码使用的是C++的方式链接这个C库文件的话,那么就会出现链接错误.
现在我们有了一个C库文件,它的头文件是f.h,产生的lib文件是f.lib,那么我们如果要在C++中使用这个库文件,我们需要这样写:
extern "C" {
#include "f.h"
}
C代码中如何调用C++ C++中如何调用C相关推荐
- 【Android 逆向】函数拦截原理 ( 通过修改 GOT 全局偏移表拦截函数 | 通过在实际被调用的函数中添加跳转代码实现函数拦截 )
文章目录 一.通过修改 GOT 全局偏移表拦截函数 二.通过在实际被调用的函数中添加跳转代码实现函数拦截 一.通过修改 GOT 全局偏移表拦截函数 使用 GOT 全局偏移表 拦截函数 , 只需要将 G ...
- 【Android 逆向】Android 进程注入工具开发 ( 注入代码分析 | 远程调用 目标进程中 libc.so 动态库中的 mmap 函数 三 | 等待远程函数执行完毕 | 寄存器获取返回值 )
文章目录 前言 一.等待远程进程 mmap 函数执行完毕 二.从寄存器中获取进程返回值 三.博客资源 前言 前置博客 : [Android 逆向]Android 进程注入工具开发 ( 注入代码分析 | ...
- 【Android 逆向】Android 进程注入工具开发 ( 注入代码分析 | 远程调用 目标进程中 libc.so 动态库中的 mmap 函数 二 | 准备参数 | 远程调用 mmap 函数 )
文章目录 一.准备 mmap 函数的参数 二.mmap 函数远程调用 一.准备 mmap 函数的参数 上一篇博客 [Android 逆向]Android 进程注入工具开发 ( 注入代码分析 | 远程调 ...
- jsp调用其他jsp中的js代码
前言 在熟悉代码时,随便选了一个按钮,规则导出的功能. 在使用F12进行debug时,发现被调用的js方法和按钮不在一个jsp页面中,感觉很神奇的调用了! 正文: 第一阶段: 通过F12查看调用的路径 ...
- js代码 父页面调用子页面中的js方法,子页面调用父页面中的js方法
文中代码亲测可用,转载以示尊重!!! <!--主页面中的JS代码--> <script type="text/javascript"> //调用子页面的方法 ...
- 【Groovy】Groovy 方法调用 ( Groovy 构造函数中为成员赋值 | Groovy 函数的参数传递与键值对参数 | 完整代码示例 )
文章目录 一.Groovy 构造函数中为成员赋值 二.Groovy 函数的参数传递与键值对参数 三.完整代码示例 一.Groovy 构造函数中为成员赋值 Groovy 类没有定义构造函数 , 但是可以 ...
- java用if语句调用方法_J2SE中main函数中的if语句想要调用另一个类的方法怎么能实现?...
日常生活中,要完成一件复杂的功能,我们总是习惯把"大功能"分解为多个"小功能"以实现.在C++程序的世界里,"功能"可称呼为"函数 ...
- Dictionary作为数据源绑定,调用c++库中返回为BYTE*的函数,listView项排序
最近在做一个电子档案管理的项目.现在还处于初期,只是做一个简单demo拿去跟客户演示.至于最后谈不谈得下来,到底做不做,反正我是不看好,但没因为这样就马马虎虎.草草了事.这个项目算是b/s加c/s混合 ...
- centos7 搭建本地git_本地服务调用K8S环境中的SpringCloud微服务实战
欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:原创文章分类汇总及配套源码,涉及Java.Docker.K8S.Devops等 下图是典型的微 ...
最新文章
- 独家 | 国内AI专业高考报考指南
- Java核心API -- 7(Iterator迭代器、Comparable、Comparator比较器)
- java绘制统计直方图取平均_统计学——直方图解析 - osc_lv8qb16y的个人空间 - OSCHINA - 中文开源技术交流社区...
- 单位阶跃信号是周期信号吗_手机信号变成“HD”,是代表没有信号吗?你的手机正在被扣费...
- java中分支_[Java教程]JavaScript中的分支结构
- es6 --- 解构赋值的简洁性
- $.get、$.post 和 $().load()
- oracle 查询不能重复,oracle – 如何防止在选择查询中选择重复行?
- 【我的物联网成长记14】车路协同,不只是车和路
- 力扣868. 二进制间距
- 添加Maven(mvn)、sbt的国内仓库
- 使用 WebSphere Portlet Factory 构建基于 Web2.0 的灵活 SOA 前端
- linux用户修改密码
- Git廖雪峰 常用命令总结
- JavaScript——利用正则表达式实现二代身份证号码的验证
- 从重大事件保障,看华为如何打造一流保障体系
- 聚类及DBSCAN 聚类算法
- UI设计中图标类型指南
- C语言练习-还原算术表达式
- python:TypeError:takes at least 8 arguments (9 given)
热门文章
- 的训练过程_指外翻的人在训练的过程中,要不要拉伸收肌?
- cron表达式 每隔8小时_cron表达式详解
- win7 linux16.04双系统,安装windows7+ubuntu16.04双系统
- 英雄会被表彰,这些技术与代码也将被历史铭记
- android滚动条布局横向,Android自定义ViewGroup实现可滚动的横向布局(2)
- java模糊查询比对方法_Java多条件和模糊查询
- 电信申请固定ip_各个代理ip之间的关系
- 牛客小白月赛12 J	月月查华华的手机 (序列自动机模板题)
- hdu 1280用hash解决。。
- Struts01---入门小案例