【转】#ifdef __cplusplus+extern "C"的用法
时常看到别人的头文件中,有这样的代码:
#ifdef __cplusplus
extern "C" {
#endif
//一段代码
#ifdef __cplusplus
}
#endif
这样的代码到底是什么意思呢?首先,__cplusplus是cpp中的自定义宏,那么定义了这个宏的话表示这是一段cpp的代码,也就是说,上面的代码的含义是:如果这是一段cpp的代码,那么加入extern "C"{,和 }处理其中的代码。
要明白为何使用extern "C",还得从cpp中对函数的重载处理开始说起。在c++中,为了支持重载机制,在编译生成的汇编码中,要对函数的名字进行一些处理,加入比如函数的返回类型等等.而在C中,只是简单的函数名字而已,不会加入其他的信息.也就是说:C++和C对产生的函数名字的处理是不一样的。使用extern "C"的目的就是实现C与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.c的实现如下:
#include "c.h"
void C_fun()
{
}
则C++的源文件(cpp.cpp)可以调用C语言源文件c.c中的C_test():
#include "c.h"
int main()
{
C_fun()
}
其中__cplusplus是C++编译器的保留宏定义.就是说C++编译器认为这个宏已经定义了。
所以关键是extern "C" {}
extern "C"是告诉C++编译器:括号里的东东是按照C的obj文件格式编译的,要连接的话按照C的命名规则去找。
注:如果你的代码不知道是被C还是C++调用时,添加这段代码可以护你周全,因为如果是c++调用的话,extern "C'声明会有效。如果时c调用的话,那么,extern "C"声明无效!
Q:那么啥时候会遇到需要使用这种写法呢?
A:因为C语言起家早,常有这样的情况:一个库文件已经用C写好了而且运行良好,这个时候如果我们使用C++编写的程序需要链接这个库文件时,那么就要加上extern "C"来修饰了,不然链接时是找不到对应的函数的。
Q:那么C中是如何调用C++文件中的函数呢?
A:因为先有C后有C++, 所以只能从C++的代码中考虑了。不但要在c++头文件中用该宏和extern "C"括起,在cpp中也要这么做。原因就是让cpp编译器将那些代码,编译成c风格。如下:
cpp.h的实现
#ifndef _c_h_
#define _c_h_
#ifdef __cplusplus
extern "C" {
#endif
void CPP_fun();
#ifdef __cplusplus
}
#endif
#endif
cpp.cpp的实现
extern "C" { //告诉C+++编译器,扩号里按照C的命名规则编译
void CPP_fun()
{
.....
}
总结
C和C++对函数的处理方式是不同的。extern "C"是使C++能够调用C编写的库文件的一个手段,如果要对编译器提示使用C的方式来处理函数的话,那么就要使用extern "C"来说明。
转自:http://blog.csdn.net/owldestiny/article/details/5772916
【转】#ifdef __cplusplus+extern "C"的用法的更多相关文章
- #ifdef __cplusplus extern c #endif 的作用
#ifdef __cplusplus // C++编译环境中才会定义__cplusplus (plus就是"+"的意思) extern "C" { // 告诉编 ...
- “#ifdef __cplusplus extern "C" { #endif”的定义
平时我们在linux c平台开发的时候,引用了一些Cpp或者C的代码库,发现一些头文件有如下代码条件编译. #ifdef __cplusplus extern "C" { #end ...
- “#ifdef __cplusplus extern "C" { #endif”的定义-----C和C++的互相调用
"#ifdef __cplusplus extern "C" { #endif"的定义 看一些程序的时候老是有 "#ifdef __cplusplus ...
- #ifdef __cplusplus extern "C" { #endif”的定义
平时我们在linux c平台开发的时候,引用了一些Cpp或者C的代码库,发现一些头文件有如下代码条件编译. #ifdef __cplusplus extern "C" { #e ...
- #ifdef __cplusplus extern "C" { #endif”的定义的含义
看一些程序的时候老是有“#ifdef __cplusplusextern "C" {#endif”的定义,搞搞清楚是怎么回事: Microsoft-Specific Predefi ...
- 备忘录:“#ifdef __cplusplus extern "C" { #endif”的定义
看一些程序的时候老是有“#ifdef __cplusplusextern "C" {#endif”的定义,搞搞清楚是怎么回事: Microsoft-Specific Predefi ...
- #ifdef __cplusplus extern "C" { #endif
1.在好多程序中我们会遇到下面代码段 #ifdef __cplusplus extern "C" { #endif //c语法代码段 #ifdef __ ...
- #ifdef __cplusplus extern "C"
#ifdef __cplusplus extern "C" { #endif //一段代码 #ifdef __cplusplus } #endif首先,__cplusplus是cp ...
- 几乎每个文件里面都有 #ifdef __cplusplus extern "C" { #endif 可我没找到程序里那个地方定义了__cplusplus 啊?这又是怎么回事呢?
我们的C语言有个进化版,叫C++,这个想必楼主知道,Keil MDK是支持C++编程的,也就是说,你可以用C语言或者C++写你的程序,都可以. 但是,有一个问题,就是头文件的问题,C语言写的头文件C+ ...
随机推荐
- tf 常用函数 28原则
一个tensorflow图由以下几部分组成: 占位符变量(Placeholder)用来改变图的输入. 模型变量(Model)将会被优化,使得模型表现得更好. 模型本质上就是一些数学函数,它根据Plac ...
- 【洛谷P4097】Segment 李超线段树
题目大意:维护一个二维平面,给定若干条线段,支持询问任意整数横坐标处对应的纵坐标最靠上的线段的 id,相同高度取 id 值较小的,强制在线. 题解:初步学习了李超线段树.李超线段树的核心思想在于通过标 ...
- des加密解密JAVA与.NET互通实例
JAVA版本 import javax.crypto.Cipher; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFacto ...
- 有趣的electron(一)
跟我一起实现一个基于electron的hello-world吧- Come with me to implement an electron-based project hello-world. 先看 ...
- textarea 字体限制,超出部分不显示并及时显示还剩字体个数
1)HTML <textarea class="box" ></textarea > 2)JQ: $(function(){ $(".box&qu ...
- Django多域名配置之Django-hosts插件的使用
使用场景: Django中有两个app,如果通过域名来访问,可以使用www.domain.com/a.www.domain.com/b来访问.这样就显得有点LowB了.如果我想通过a.domain.c ...
- Python 爬虫的工具列表 附Github代码下载链接
Python爬虫视频教程零基础小白到scrapy爬虫高手-轻松入门 https://item.taobao.com/item.htm?spm=a1z38n.10677092.0.0.482434a6E ...
- 函数和常用模块【day06】:xml模块(六)
本节内容 1.简述 2.xml格式 3.xml节点操作 4.创建新的xml文件 一.简述 xml是实现不同语言或者程序之间进行数据交换的协议,跟json差不多,但是json使用起来更简单,不过,古时候 ...
- 函数和常用模块【day04】:函数参数及调用(二)
本节内容 1.为什么要有参数 2.返回值 3.有参数函数调用 一.为什么要有参数? 无参数实现 def CPU报警邮件() #发送邮件提醒 连接邮箱服务器 发送邮件 关闭连接 def 硬盘报警邮件() ...
- css3让图文不能复制
-webkit-user-select: none; -ms-user-select: none; -moz-user-select: none; -khtml-user-select: none; ...