1 问题提出

在编程过程中,经常发现如下用法:

#ifndef _FILE_NAME_H_
#define _FILE_NAME_H_ #ifdef __cplusplus
extern "C" {
#endif ...... #ifdef __cplusplus
}
#endif
 
#endif

这样的代码到底是什么意思呢?首先,__cplusplus是cpp中自定义的宏,那么定义了这个宏的话表示这是一段cpp的代码,也就是说,上面的代码的含义是:如果这是一段cpp的代码,那么加入extern "C"{和}处理其中的代码。

要明白为何使用extern "C",还得从cpp中对函数的重载处理开始说起。在c++中,为了支持重载机制,在编译生成的汇编码中,要对函数的名字进行一些处理,加入比如函数的返回类型等等。而在C中,只是简单的函数名字而已,不会加入其他的信息,也就是说:C++和C对产生的函数名字的处理是不一样的,extern "C"的目的就是主要实现C与C++的相互调用问题。

2 c++中调用c函数

使用场景:

1、 由于系统内核一般是使用C语言来编写的,系统内核中用C语言实现了很多库。而上层应用程序有可能是用C++来开发,如果在内核库函数头文件中不用 extern “C”来声明库函数的话,在编写C++应用程序时,包含库头文件,在C++文件链接时就会以C++标准来链接库的函数名,而在库文件实现时是用C来实现的,二者函数名不同,在链接时就会出现找不到函数的现象。

2、在个人开发工程中,个人熟悉使用c++语言,当.cpp文件要调用.c文件中的函数时,需要extern "C"声明.c文件中的函数,在cpp文件中让c++编译器使用c标准链接c文件中函数。

具体实现:

C函数头文件实现:

//c.h
#ifndef _c_h_
#define _c_h_ #ifdef __cplusplus
extern "C" {
#endif void c_fun(); #ifdef __cplusplus
}
#endif #endif

C函数源文件实现:

#include "c.h"

void c_fun()
{ }

C++调用C函数实现:example.cpp中调用c_func函数,

//example.cpp实现

#include "c.h"
int main()
{
c_fun();
     return 0;
}

3 c中调用c++函数

当extern “C”放在函数声明之前,并不会改变函数的编译方式,只是指定编译器按照C的标准链接,而不是按照C++的标准去链接函数。因此,如果c++的库要给c调用,显然,不但要在c++头文件中用该宏和extern "c"括起,在cpp中也要这么做。原因就是让cpp编译器将那些代码,编译成c风格。(在Visual Stduio 2010环境中,在c++函数源文件中不使用extern "c",编译出来的函数名字也是按照c风格,而不是c++风格,与前面的在cpp中也需要添加extern "c"不一致,留待后面论证。)

c++函数头文件实现:

#ifndef _cpp_h_
#define _cpp_h_
#ifdef __cplusplus
extern "C" {
#endif void cpp_fun(); #ifdef __cplusplus
}
#endif #endif

c++函数源文件实现:

#include "cpp.h"

extern "C" {    //告诉C++编译器,扩号里按照C的命名规则编译
void cpp_fun()
{ }

}

在c中调用c++函数,example.c调用cpp_fun函数:

//example.c实现

#include "cpp.h"

int main()
{
cpp_fun();
return 0;
}

上述方案只适合调用C++中的非成员函数,如果你想要在 C 里调用成员函数(包括虚函数),则需要提供一个简单的包装(wrapper)。具体方案参考如下博文:

C如何调用C++中函数

4 参考资料

http://blog.csdn.net/hxg130435477/article/details/6632954

http://blog.csdn.net/miyunhong/article/details/4589541

extern “C”原理,用法以及使用场景-2016.01.05的更多相关文章

  1. 2016.01.05 DOM笔记(一) 查找元素

    DOM节点的种类 元素和标签是一个意思,例如<body>标签或者称为<body>元素 节点DOM的节点分为三类  元素节点,文本节点,属性节点 例如 <div id=‘b ...

  2. extern “C”调用测试与验证-2016.01.06

    1 调用情形说明 在上一篇关于extern “c”原理以及用法中,详细的说明了为什么需要extern “c”以及如何使用它解决c与c++混合编程时遇到的问题.接下来,使用示例验证方式验证c与c++函数 ...

  3. C/C++之extern "C"的用法解析

    extern "C"的用法解析 http://blog.sina.com.cn/u/494a1ebc010004g5 C++中extern “C”含义深层探索 1.引言 C++语言 ...

  4. ZT extern "C"的用法解析

    extern "C"的用法解析 1.引言 C++语言的创建初衷是“a better C”,但是这并不意味着C++中类似C语言的全局变量和函数所采用的编译和连接方式与C语言完全相同. ...

  5. extern的原理很简单,就是告诉编译器:“你现在编译的文件中,有一个标识符虽然没有在本文件中定义,但是它是在别的文件中定义的全局变量,你要放行!”

    extern的原理很简单,就是告诉编译器:“你现在编译的文件中,有一个标识符虽然没有在本文件中定义,但是它是在别的文件中定义的全局变量,你要放行!”

  6. 阿里P8架构师谈:数据库分库分表、读写分离的原理实现,使用场景

    本文转载自:阿里P8架构师谈:数据库分库分表.读写分离的原理实现,使用场景 为什么要分库分表和读写分离? 类似淘宝网这样的网站,海量数据的存储和访问成为了系统设计的瓶颈问题,日益增长的业务数据,无疑对 ...

  7. [官方软件] Easy Sysprep v4.3.29.602 【系统封装部署利器】(2016.01.22)--skyfree大神

    [官方软件] Easy Sysprep v4.3.29.602 [系统封装部署利器](2016.01.22) Skyfree 发表于 2016-1-22 13:55:55 https://www.it ...

  8. http://tedhacker.top/2016/08/05/Spring%E7%BA%BF%E7%A8%8B%E6%B1%A0%E4%BD%BF%E7%94%A8%E6%96%B9%E6%B3%95/

    http://tedhacker.top/2016/08/05/Spring%E7%BA%BF%E7%A8%8B%E6%B1%A0%E4%BD%BF%E7%94%A8%E6%96%B9%E6%B3%9 ...

  9. Murano Weekly Meeting 2016.07.05

    Meeting time: 2016.July.05 1:00~2:00 Chairperson:  Kirill Zaitsev, from Mirantis Meeting summary: 1. ...

随机推荐

  1. Scala第四章学习笔记(面向对象编程)

    延迟构造 DelayedInit特质是为编译器提供的标记性的特质.整个构造器被包装成一个函数并传递给delayedInit方法. trait DelayedInit { def deayedInit( ...

  2. Spark运行流程概述

    Application 指用户编写的Spark应用程序,其中包含了一个Driver功能的代码和分布在集群中多个节点上运行的Executor代码. Driver Spark中的Driver即运行上述Ap ...

  3. c# 函数及out传值

    使用 out传值的时候仅仅是将变量名(箱子)拿过来,并不会管之前是什么值函数体结束之前必须对该out的参数进行赋值,否则报错(不好意思还回去)out传值,可以进行多个值的传回 public void ...

  4. 使用UltraEdit+BCC5.5搭建C语言学习环境(转)

    今天闲来无聊,想起以前学的C都差不多忘光了,想练练,先搭环境吧,vc bc之类都太大了,我以前在borland下过一个命令行编译工具不错,好像以前看到有人用ultraedit配合命令行工具做过一个开发 ...

  5. purple-class2-默认选项切换

    ylbtech-class:purple-class2 A, 返回顶部 1,默认选项切换 #region 默认选项切换 public delegate IList<SelectListItemI ...

  6. jsp页面的使用

    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, ...

  7. [ActionScript 3.0] AS3 时间格式化方法

    /** * 格式化时间,格式 00:00:00 * @param total 总时间(毫秒) */ function getFormatTime(total:uint):String { if (to ...

  8. 封装一个简单好用的打印Log的工具类And快速开发系列 10个常用工具类

    快速开发系列 10个常用工具类 http://blog.csdn.net/lmj623565791/article/details/38965311 ------------------------- ...

  9. IRasterClassifyColorRampRenderer 使用时的一些奇怪的地方 (转)

    1.IRasterClassifyColorRampRenderer 的Break设置方法 IRasterClassifyColorRampRenderer这个接口是ArcEngine里对单波段栅格影 ...

  10. SecureCRT的背景和文字颜色的修改

    options->;session options->;emulation->;terminal选择linux(相应的服务器系统)ansi color 打上钩options-> ...