C代码中如何调用C++ C++中如何调用C

1. 在C++中调用C:使用extern "C"则是告诉编译器依照C的方式来编译封装接口,当然接口函数里面的C++语法还是按C++方式编译

包装(wrapper)

2. 在C中调用C++:extern "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  

其中__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"

}

版权声明:本文为【借你一秒】原创文章,转载请标明出处。

时间: 2024-10-12 15:38:54

C代码中如何调用C++ C++中如何调用C的相关文章

浏览器中的JavaScript执行机制:08 | 调用栈:为什么JavaScript代码会出现栈溢出?

前言:该篇说明:请见 说明 —— 浏览器工作原理与实践 目录 在上篇文章中,我们讲到了,当一段代码被执行时,JavaScript 引擎先会对其进行编译,并创建执行上下文.但是并没有明确说明到底什么样的代码才算符合规范. 那么接下来我们就来明确下,哪些情况下代码才算是“一段”代码,才会在执行之前就进行编译并创建执行上下文.一般说来,有这么三种情况: 1.当 JavaScript 执行全局代码的时候,会编译全局代码并创建全局执行上下文,而且在整个页面的生存周期内,全局执行上下文只有一份. 2.当调用

绑定服务调用本地服务中的方法

如果想调用服务中的方法, 通过startService()是做不到的, 这时需要用bindService来解决. 下面的demo是在Activity中调用Service中的自定义方法---methodInService 这个demo可以解决在项目开发中调用service里的数据. 这里在service中使用到了代理模式.这是为了,给service组件和activity组件中间添加一个中间人. 通过代理来传递数据.也就是binder对象.这个代理就是接口IService Service中的代码如下

python中的嵌套类(内部类调用外部类中的方法函数)

在为书中版本是3.X的,但2.X不太支持直接调用. 所以,在PYTHON2.X中,要在内部类中调用外部类的方法,就必须得实例化外部类,然后,传入实例进行调用. 花了我两个小时啊,资料没找到,自己一个一个想法调试,真的失败了三四十次,PRINT了N多~~~:) class DiagramFactory: @classmethod def make_diagram(Class, width, height): return Class.Diagram(width, height) @classmet

C#反射调用程序集类中方法

建立类 class OperatorClass { /// <summary> /// 加法 /// </summary> /// <param name="x"></param> /// <param name="y"></param> /// <returns></returns> /// public static int Add(int x, int y) { r

MFC OnPaint()函数中最先调用CDialog::OnPaint()和最后调用CDialog::OnPaint()的巨大区别

OnPaint()函数中最先调用CDialog::OnPaint()和最后调用CDialog::OnPaint()的巨大区别,如果没有注意这个问题就会出现无厘头式的绘图问题-- 效果就是出不来!在经过两个多小时的折磨后法相问题所在,总结出教训: OnPaint()函数中首先就调用CDialog::OnPaint()函数: [cpp] view plain copy //给主窗体客户区添加位图背景 void CBackimageDlg::OnPaint() { CDialog::OnPaint()

C# winForm中调用javascript文件中的方法

目前有很多的SNS社区或类SNS的网站,例如开心.51.校内等,但是发现大多数社区在邀请好友的时候都没有提供对QQ邮箱或者QQ空间好友列表获取的功能,不过似乎海内支持,但是网上相关QQ的文章还不是很多,希望这篇文章能给你带来一些帮助. QQ空间及邮箱登陆的校验方式: QQ空间及邮箱登陆的时候,用户输入的密码首先会被页面中的一段Js加密,然后加密过后的密码会加上验证码形成一个新的字串,接着这个新的字串被MD5(32位)加密,加密过后形成最终的密码,这就是我们为什么经常会发现我们在提交的时候我们的密

一行代码,让你的应用中UIScrollView的滑动与侧滑返回并存

一行代码,让你的应用中UIScrollView的滑动与侧滑返回并存 侧滑返回是iOS系统的一个很贴心的功能,特别是在大屏手机上,单手操作的时候去按左上角的返回键特别不方便.当我在使用一个APP的时候,如果控制器不能侧滑返回,我会觉得这个APP十分不友好...这款产品在我心中的印象分也会有所降低...侧滑返回本身是系统自带的效果,无须开发者处理的.但是,一旦给控制器加了leftBarButtonItem,系统侧滑手势居然失效了(苹果你这样真的好吗...),要重新支持侧滑返回,可以做以下处理: 一.

Native Application 开发详解(直接在程序中调用 ntdll.dll 中的 Native API,有内存小、速度快、安全、API丰富等8大优点)

文章目录:                   1. 引子: 2. Native Application Demo 展示: 3. Native Application 简介: 4. Native Application 有何妙用: 5. MJ0011 关于 Native Application 的文章整理: 6. 互联网上其他关于 Native Application 的文章整理: 7. 小结: 1. 引子: 其实在好久以前就看了 MJ0011 翻译的那个<Native 应用程序详细>系列的文

opp思想、代码规范、单例模式、php中引号问题以及include用法

关于OPP(Object Oriented Programming(此内容参照百度百科)): 面向对象程序设计不同于面向过程程序设计,它将一件复杂的事情拆分成一个一个的块对象,然后对块进行分析,实现块级的动作.最后把一个一个的块像搭积木一样组成复杂的事件.可以说,OPP大大地降低了软件开发的难度. OPP达到了软件工程的三个主要目标:重用性.灵活性和扩展性. OPP的主要特性: **抽象性 -- 程序有能力忽略正在处理的信息某些方面的能力.也就是说对信息某些主要方面关注,次要方面忽略. 信息封装