注意这里的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  

其中__cplusplus是C++编译器的保留宏定义.就是说C++编译器认为这个宏已经定义了.
所以关键是extern "C" {}
extern "C"是告诉C++编译器件括号里的东东是按照C的obj文件格式编译的,要连接的话按照C的命名规则去找.

  要明白为何使用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相关推荐

  1. 【Android 逆向】函数拦截原理 ( 通过修改 GOT 全局偏移表拦截函数 | 通过在实际被调用的函数中添加跳转代码实现函数拦截 )

    文章目录 一.通过修改 GOT 全局偏移表拦截函数 二.通过在实际被调用的函数中添加跳转代码实现函数拦截 一.通过修改 GOT 全局偏移表拦截函数 使用 GOT 全局偏移表 拦截函数 , 只需要将 G ...

  2. 【Android 逆向】Android 进程注入工具开发 ( 注入代码分析 | 远程调用 目标进程中 libc.so 动态库中的 mmap 函数 三 | 等待远程函数执行完毕 | 寄存器获取返回值 )

    文章目录 前言 一.等待远程进程 mmap 函数执行完毕 二.从寄存器中获取进程返回值 三.博客资源 前言 前置博客 : [Android 逆向]Android 进程注入工具开发 ( 注入代码分析 | ...

  3. 【Android 逆向】Android 进程注入工具开发 ( 注入代码分析 | 远程调用 目标进程中 libc.so 动态库中的 mmap 函数 二 | 准备参数 | 远程调用 mmap 函数 )

    文章目录 一.准备 mmap 函数的参数 二.mmap 函数远程调用 一.准备 mmap 函数的参数 上一篇博客 [Android 逆向]Android 进程注入工具开发 ( 注入代码分析 | 远程调 ...

  4. jsp调用其他jsp中的js代码

    前言 在熟悉代码时,随便选了一个按钮,规则导出的功能. 在使用F12进行debug时,发现被调用的js方法和按钮不在一个jsp页面中,感觉很神奇的调用了! 正文: 第一阶段: 通过F12查看调用的路径 ...

  5. js代码 父页面调用子页面中的js方法,子页面调用父页面中的js方法

    文中代码亲测可用,转载以示尊重!!! <!--主页面中的JS代码--> <script type="text/javascript"> //调用子页面的方法 ...

  6. 【Groovy】Groovy 方法调用 ( Groovy 构造函数中为成员赋值 | Groovy 函数的参数传递与键值对参数 | 完整代码示例 )

    文章目录 一.Groovy 构造函数中为成员赋值 二.Groovy 函数的参数传递与键值对参数 三.完整代码示例 一.Groovy 构造函数中为成员赋值 Groovy 类没有定义构造函数 , 但是可以 ...

  7. java用if语句调用方法_J2SE中main函数中的if语句想要调用另一个类的方法怎么能实现?...

    日常生活中,要完成一件复杂的功能,我们总是习惯把"大功能"分解为多个"小功能"以实现.在C++程序的世界里,"功能"可称呼为"函数 ...

  8. Dictionary作为数据源绑定,调用c++库中返回为BYTE*的函数,listView项排序

    最近在做一个电子档案管理的项目.现在还处于初期,只是做一个简单demo拿去跟客户演示.至于最后谈不谈得下来,到底做不做,反正我是不看好,但没因为这样就马马虎虎.草草了事.这个项目算是b/s加c/s混合 ...

  9. centos7 搭建本地git_本地服务调用K8S环境中的SpringCloud微服务实战

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:原创文章分类汇总及配套源码,涉及Java.Docker.K8S.Devops等 下图是典型的微 ...

最新文章

  1. 独家 | 国内AI专业高考报考指南
  2. Java核心API -- 7(Iterator迭代器、Comparable、Comparator比较器)
  3. java绘制统计直方图取平均_统计学——直方图解析 - osc_lv8qb16y的个人空间 - OSCHINA - 中文开源技术交流社区...
  4. 单位阶跃信号是周期信号吗_手机信号变成“HD”,是代表没有信号吗?你的手机正在被扣费...
  5. java中分支_[Java教程]JavaScript中的分支结构
  6. es6 --- 解构赋值的简洁性
  7. $.get、$.post 和 $().load()
  8. oracle 查询不能重复,oracle – 如何防止在选择查询中选择重复行?
  9. 【我的物联网成长记14】车路协同,不只是车和路
  10. 力扣868. 二进制间距
  11. 添加Maven(mvn)、sbt的国内仓库
  12. 使用 WebSphere Portlet Factory 构建基于 Web2.0 的灵活 SOA 前端
  13. linux用户修改密码
  14. Git廖雪峰 常用命令总结
  15. JavaScript——利用正则表达式实现二代身份证号码的验证
  16. 从重大事件保障,看华为如何打造一流保障体系
  17. 聚类及DBSCAN 聚类算法
  18. UI设计中图标类型指南
  19. C语言练习-还原算术表达式
  20. python:TypeError:takes at least 8 arguments (9 given)

热门文章

  1. 的训练过程_指外翻的人在训练的过程中,要不要拉伸收肌?
  2. cron表达式 每隔8小时_cron表达式详解
  3. win7 linux16.04双系统,安装windows7+ubuntu16.04双系统
  4. 英雄会被表彰,这些技术与代码也将被历史铭记
  5. android滚动条布局横向,Android自定义ViewGroup实现可滚动的横向布局(2)
  6. java模糊查询比对方法_Java多条件和模糊查询
  7. 电信申请固定ip_各个代理ip之间的关系
  8. 牛客小白月赛12 J 月月查华华的手机 (序列自动机模板题)
  9. hdu 1280用hash解决。。
  10. Struts01---入门小案例