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. PLSQL_性能优化系列18_Oracle Explain Plan解析计划通过Baseline绑定

    2015-05-28 Created By BaoXinjian

  2. HDU 1532 (Dinic算法)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1532 题目大意: 就是由于下大雨的时候约翰的农场就会被雨水给淹没,无奈下约翰不得不修建水沟,而且是网络 ...

  3. 51nod 1120 机器人走方格 V3 卡特兰数 lucas定理

    N * N的方格,从左上到右下画一条线.一个机器人从左上走到右下,只能向右或向下走.并要求只能在这条线的上面或下面走,不能穿越这条线,有多少种不同的走法?由于方法数量可能很大,只需要输出Mod 100 ...

  4. POJ 3162 Walking Race 树形DP+线段树

    给出一棵树,编号为1~n,给出数m 漂亮mm连续n天锻炼身体,每天会以节点i为起点,走到离i最远距离的节点 走了n天之后,mm想到知道自己这n天的锻炼效果 于是mm把这n天每一天走的距离记录在一起,成 ...

  5. ADO.NET(完整修改和查询、实体类,数据访问类)

    一.完整修改和查询 在编写c#语句时需考虑到用户体验,例如在编写修改语句时,需要考虑到输入的内容在数据库中是否能够找到. 中间变量运用. 1.先查 2.执行操作 完整修改语句: bool has = ...

  6. ylbtech-dbs:ylbtech-4,PurpleHouse(房地产楼盘销售系统)

    ylbtech-dbs:ylbtech-4,PurpleHouse(房地产楼盘销售系统) -- =============================================-- Crea ...

  7. 树莓派:使用OpenCV调用自带的摄像头.

    总所周知,树莓派上,调用摄像头的指令有raspistill和raspivid.若要使用opencv对摄像头进行调用,不少人会出现 cvCaptureFromCAM(0)函数无法找到Pi Cam的错误情 ...

  8. python第一个hello world注意问题!!

    如果你第一次写python代码,想写一个通常的hello world ,那么你需要注意这个hello world的写法,这和python的版本有直接关系!!! Python 3.x: print('h ...

  9. [ActionScript 3.0] Away3D 灯光的使用

    package { import away3d.containers.View3D; import away3d.entities.Mesh; import away3d.events.MouseEv ...

  10. Java中Map的用法

    Map的一般用法 1.声明一个Map : Map map = new HashMap(); 2 .向map中放值 ,注意: map是key-value的形式存放的,如: map.put("s ...