当前位置: 首页 > 编程日记 > 正文

C++中extern C的使用

C++程序有时需要调用其它语言编写的函数,最常见的是调用C语言编写的函数。像所有其它名字一样,其它语言中的函数名字也必须在C++中进行声明,并且该声明必须指定返回类型和形参列表。对于其它语言编写的函数来说,编译器检查其调用的方式与处理普通C++函数的方式相同,但是生成的代码有所区别。C++使用链接指示(linkage  directive)指出任意非C++函数所用的语言

链接指示(linkage directive):支持C++程序调用其它语言编写的函数的一种机制。所有编译器都应支持调用C++和C函数,至于是否支持其它语言则由编译器决定。

要想把C++代码和其它语言(包括C语言)编写的代码放在一起使用,要求我们必须有权访问该语言的编译器,并且这个编译器与当前的C++编译器是兼容的。

声明一个非C++的函数:链接指示可以有两种形式:单个的或复合的。链接指示不能出现在类定义或函数定义的内部。同样的链接指示必须在函数的每个声明中都出现。

链接指示的第一种形式包含一个关键字extern,后面是一个字符串字面值常量以及一个”普通的”函数声明。其中的字符串字面值常量指出了编写函数所用的语言。编译器应该支持对C语言的链接指示。此外,编译器也可能会支持其它语言的链接指示,如extern “Ada”、extern “FORTRAN”等。

链接指示与头文件:我们可以令链接指示后面跟上花括号括起来的若干函数的声明,从而一次性建立多个链接。花括号的作用是将适用于该链接指示的多个声明聚合在一起,否则花括号就会被忽略,花括号中声明的函数名字就是可见的,就好像在花括号之外声明的一样。多重声明的形式可以应用于整个头文件。

当一个#include指示被放置在复合链接指示的花括号中时,头文件中的所有普通函数声明都被认为是由链接指示的语言编写的。链接指示可以嵌套,因此如果头文件包含带自带链接指示的函数,则该函数的链接不受影响。

C++从C语言继承的标准库函数可以定义成C函数,但并非必须:决定使用C还是C++实现C标准库,是每个C++实现的事情。

指向extern “C”函数的指针:编写函数所用的语言是函数类型的一部分。因此,对于使用链接指示定义的函数来说,它的每个声明都必须使用相同的链接指示。而且,指向其它语言编写的函数的指针必须与函数本身使用相同的链接指示。指向C函数的指针与指向C++函数的指针是不一样的类型。一个指向C函数的指针不能用在指向初始化或赋值操作后指向C++函数,反之亦然。就像其它类型不匹配的问题一样,如果我们试图在两个链接指示不同的指针之间进行赋值操作,则程序将发生错误。

链接指示对整个声明都有效:当我们使用链接指示时,它不仅对函数有效,而且对作为返回类型或形参类型的函数指针也有效。因为链接指示同时作用于声明语句中的所有函数,所以如果我们希望给C++函数传入一个指向C函数的指针,则必须使用类型别名

导出C++函数到其它语言:通过使用链接指示对函数进行定义,我们可以令一个C++函数在其它语言编写的程序中可用。值得注意的是,可被多种语言共享的函数的返回类型或形参类型受到很多限制。例如,我们不太可能把一个C++类的对象传给C程序,因为C程序根本无法理解构造函数、析构函数以及其它类特有的操作。

对链接到C的预处理器的支持:有时需要在C和C++中编译同一个源文件,为了实现这一目的,在编译C++版本的程序时预处理器定义__cplusplus(两个下划线)。利用这个变量,我们可以在编译C++程序的时候有条件地包含进来一些代码。

重载函数与链接指示:链接指示与重载函数的相互作用依赖于目标语言。如果目标语言支持重载函数,则为该语言实现链接指示的编译器很可能也支持重载这些C++的函数。C语言不支持函数重载,因此也就不难理解为什么一个C链接指示只能用于说明一组重载函数中的某一个了。如果在一组重载函数中有一个是C函数,则其余的必定都是C++函数。

C++虽然兼容C,但C++文件中函数编译后生成的符号与C语言生成的不同。相同的函数,在C和C++中,编译后生成的符号不同。

extern"C"的主要作用就是为了能够正确实现C++代码调用其它C语言代码。加上extern "C"后,会指示编译器这部分代码按C语言的进行编译,而不是C++的。由于C++支持函数重载,因此编译器编译函数的过程中会将函数的参数类型也加到编译后的代码中,而不仅仅是函数名;而C语言并不支持函数重载,因此编译C语言代码的函数时不会带上函数的参数类型,一般只包括函数名。

extern "C" makes a function-name in C++ have 'C' linkage (compiler does not mangle the name) so that client C code can link to (i.e use) your function using a 'C' compatible header file that contains just the declaration of your function. Your function definition is contained in a binary format (that was compiled by your C++ compiler) that the client 'C' linker will then link to using the 'C' name.

Since C++ has overloading of function names and C does not, the C++ compiler cannot just use the function name as a unique id to link to, so it mangles the name by adding information about the arguments. A C compiler does not need to mangle the name since you can not overload function names in C. When you state that a function has extern "C" linkage in C++, the C++ compiler does not add argument/parameter type information to the name used for linkage.

Just so you know, you can specify "C" linkage to each individual declaration/definition explicitly or use a block to group a sequence of declarations/definitions to have a certain linkage. (from:  https://stackoverflow.com/questions/1041866/in-c-source-what-is-the-effect-of-extern-c )

下面是从其他文章中copy的测试代码,详细内容介绍可以参考对应的reference:

c_head.h:

#ifndef FBC_CPPBASE_C_HEAD_H_
#define FBC_CPPBASE_C_HEAD_H_void tmp_f(void);#endif // FBC_CPPBASE_C_HEAD_H_
c_head.c:

#include "c_head.h"
#include <stdio.h>void tmp_f(void)
{fprintf(stdout, "\n This is a C code\n");
}
extern_c.hpp:

#ifndef FBC_CPPBASE_EXTERN_C_HPP_
#define FBC_CPPBASE_EXTERN_C_HPP_namespace extern_c_ {// the first method
#ifdef __cplusplus
extern "C" {
#include "c_head.h"
}
#endif// the second method
//extern "C" void tmp_f(void);int test_extern_c_1();} // namespace extern_c_#endif // FBC_CPPBASE_EXTERN_C_HPP_
extern_c.cpp:

#include "extern_c.hpp"
#include <iostream>namespace extern_c_ {
//
// reference: http://www.thegeekstuff.com/2013/01/mix-c-and-cpp/
int test_extern_c_1()
{tmp_f();return 0;
}///
// reference: https://stackoverflow.com/questions/1292138/when-to-use-extern-c-in-c
/*extern "C" makes names not mangled.It used when:1. We need to use some C library in C++extern "C" int foo(int);2. We need export some C++ code to Cextern "C" int foo(int) { something; }3. We need an ability to resolve symbol in shared library -- so we need to get rid manglingextern "C" int foo(int) { something; }typedef int (*foo_type)(int);foo_type f = (foo_type)dlsym(handle,"foo")
*/} // namespace extern_c_

GitHub: https://github.com/fengbingchun/Messy_Test

相关文章:

Linux之tmpwatch命令

1、tmpwatch命令功能简介[rootvms002 /]# whatis tmpwatch tmpwatch (8) - removes files which havent been accessed for a period of... #删除一段时间内未被访问的文件tmpwatch删除最近一段时间内没有被访问的文件&#xff0c;时间以小时为单位&#xff0c;节省磁盘空间。…

你不得不知道的Visual Studio 2012(1)- 每日必用功能

2019独角兽企业重金招聘Python工程师标准>>> Visual Studio 2012已经正式发布&#xff0c;有很多花哨的新特性&#xff0c;也有很多方便使用者的新功能&#xff0c;当然也有负面声音。对于我们程序员&#xff0c;最关心的还是如何快速掌握VS2012&#xff0c;用于平时…

C++11中std::unique_lock的使用

std::unique_lock为锁管理模板类&#xff0c;是对通用mutex的封装。std::unique_lock对象以独占所有权的方式(unique owership)管理mutex对象的上锁和解锁操作&#xff0c;即在unique_lock对象的声明周期内&#xff0c;它所管理的锁对象会一直保持上锁状态&#xff1b;而unique…

为何Google将几十亿行源代码放在一个仓库?| CSDN博文精选

作者 | Rachel Potvin&#xff0c;Josh Levenberg译者 | 张建军编辑 | apddd【AI科技大本营导读】与大多数开发者的想象不同&#xff0c;Google只有一个代码仓库——全公司使用不同语言编写的超过10亿文件&#xff0c;近百TB源代码都存放在自行开发的版本管理系统Piper中&#…

小小hanoi

为什么80%的码农都做不了架构师&#xff1f;>>> View Code #include " iostream " using namespace std; int k 0 ; void hanoi( int m , char a , char b, char c){ if (m 1 ) { k ; printf( " %c->%c " ,a , c); return…

Unity3D心得分享

本篇文章的内容以各种tips为主&#xff0c;不间断更新 2019/05/10 最近更新&#xff1a; 使用Instantiate初始化参数去实例对象 Unity DEMO学习 Unity3D Adam Demo的学习与研究 Unity3D The Blacksmith Demo部分内容学习 Viking Village维京村落demo中的地面积水效果 Viking V…

django搭建示例-ubantu环境

python3安装--------------------------------------------------------------------------- 最新的django依赖python3,同时ubantu系统默认自带python2与python3&#xff0c;这里单独安装一套python3&#xff0c;并且不影响原来的python环境 django demo使用sqlite3&#xff0c…

C++11中std::lock_guard的使用

互斥类的最重要成员函数是lock()和unlock()。在进入临界区时&#xff0c;执行lock()加锁操作&#xff0c;如果这时已经被其它线程锁住&#xff0c;则当前线程在此排队等待。退出临界区时&#xff0c;执行unlock()解锁操作。更好的办法是采用”资源分配时初始化”(RAII)方法来加…

OpenAI机械手单手轻松解魔方,背靠强化学习+新技术ADR

编译 | 夕颜出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09;【导读】10月15日&#xff0c;人工智能研究机构OpenAI发布了一条机械手单手解魔方的视频。这个自学式的类人机器人手臂名为 Dactyl&#xff0c;不仅可以单手解魔方&#xff0c;甚至能在外加各种干扰&#x…

AMD and CMD are dead之js模块化黑魔法

缘由 在2013-03-06 13:58的时候&#xff0c;曾甩下一片文章叫&#xff1a;《为什么不使用requirejs和seajs》&#xff0c;并放下豪言说发布一款完美的模块化库&#xff0c;再后来就把那篇文章删了&#xff0c;再然后就没有然后。该用seajs还用seajs&#xff0c;甚至我码的SCJ都…

一文了解Python常见的序列化操作

关于我 编程界的一名小小程序猿&#xff0c;目前在一个创业团队任team lead&#xff0c;技术栈涉及Android、Python、Java和Go&#xff0c;这个也是我们团队的主要技术栈。 联系&#xff1a;hylinux1024gmail.com 0x00 marshal marshal使用的是与Python语言相关但与机器无关的二…

TEE(Trusted Execution Environment)简介

TEE(Trusted Execution Environment)&#xff0c;可信执行环境&#xff0c;该环境可以保证不被常规操作系统干扰的计算&#xff0c;因此称为”可信”。这是通过创建一个可以在TrustZone的”安全世界”中独立运行的小型操作系统实现的&#xff0c;该操作系统以系统调用(由TrustZ…

自动驾驶关键环节:行人的行为意图建模和预测(上)

作者 | 黄浴出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09;【导读】介绍一下最近行人行为意图建模和预测的研究工作&#xff0c;还是分上下两部分&#xff0c;本文为上半部分。Social LSTM: Human Trajectory Prediction in Crowded Spaces比较早的是斯坦福大学 201…

自定义windows下自动清除文件夹或者文件的只读属性的脚本

脚本内容入下&#xff1a;其中脚本中 ”/d"作用 &#xff08;可以用来改变当前驱动器目录&#xff09;例如&#xff1a; 我现在是在D盘&#xff0c;现在我要切换到C:\windows目录 脚本参数中 ATTRIB -R /S /D 解释内容如下&#xff1a;&#xff08;上述脚本参数中的 cd …

C++11容器中新增加的emplace相关函数的使用

C11中&#xff0c;针对顺序容器(如vector、deque、list)&#xff0c;新标准引入了三个新成员&#xff1a;emplace_front、emplace和emplace_back&#xff0c;这些操作构造而不是拷贝元素。这些操作分别对应push_front、insert和push_back&#xff0c;允许我们将元素放置在容器头…

Silverlight+WCF 新手实例 象棋 主界面-棋谱-获取列表(三十八)

2019独角兽企业重金招聘Python工程师标准>>> 在线演示地址&#xff1a;SilverlightWCF 新手实例 象棋 在线演示 在SilverlightWCF 新手实例 象棋 主界面-棋谱-布局写谱(三十六)中&#xff0c;我们完成下棋双方的棋谱显示&#xff0c;这节&#xff0c;我们为观众增加…

确认!语音识别大牛Daniel Povey将入职小米,曾遭霍普金斯大学解雇,怒拒Facebook

整理 | 夕颜 出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09; 【导读】10 月 17 日&#xff0c;语音界传奇 Daniel Povey 发布推特&#xff0c;宣布自己 2019 年末将要入职小米&#xff0c;目前正在签订合同阶段&#xff0c;入职后&#xff0c;他将带领一支团队研发…

软链接与硬链接

$ ln f1 f2 #创建f1的一个硬连接文件f2$ ln -s f1 f3 #创建f1的一个符号连接文件f3$ ls -li # -i参数显示文件的inode节点信息转载于:https://www.cnblogs.com/zhizouxiao/p/3794668.html

一文读懂Python复杂网络分析库networkx | CSDN博文精选

作者 | yyl424525来源 | CSDN博客文章目录1. 简介安装支持四种图绘制网络图基本流程2. Graph-无向图节点边属性有向图和无向图互转3. DiGraph-有向图一些精美的图例子环形树状图权重图Giant ComponentRandom Geometric Graph 随机几何图节点颜色渐变边的颜色渐变Atlas画个五角星…

C++11多线程中std::call_once的使用

C11中的std::call_once函数位于<mutex>头文件中。在多线程编程中&#xff0c;有时某个任务只需要执行一次&#xff0c;此时可以用C11中的std::call_once函数配合std::once_flag来实现。如果多个线程需要同时调用某个函数&#xff0c;std::call_once可以保证多个线程对该函…

Solaris 上网配置

2019独角兽企业重金招聘Python工程师标准>>> 早上装solaris10系统的时候&#xff0c;没选默认&#xff0c;选了desk-session模式安装。全英文无界面安装&#xff0c;中间还跑出几个乱码。 靠着随便选随便F2&#xff0c;终于安装完了。 就在那设完分辨率后&#xff0…

Configure,Makefile.am, Makefile.in, Makefile文件之间关系

为什么80%的码农都做不了架构师&#xff1f;>>> 1.autoscan (autoconf): 扫描源代码以搜寻普通的可移植性问题&#xff0c;比如检查编译器&#xff0c;库&#xff0c;头文件等&#xff0c;生成文件configure.scan,它是configure.ac的一个雏形。 your source files…

这款耳机一点不输千元级的AirPods

你如果问我&#xff1a;生活中你觉得必不可少的一件电子产品是什么&#xff1f;那么我会毫不犹豫的回答你&#xff1a;是耳机&#xff01;出门忘带耳机是绝对不能忍听不听没关系&#xff0c;但是有它比较安心我觉得生活中不仅是我很多人都对耳机有一种依赖因为很多人都喜欢音乐…

CUDA Samples: Image Process: BGR to Gray

在图像处理中&#xff0c;颜色变换BGR到Gray&#xff0c;常见的一般有两种计算方式&#xff0c;一种是基于浮点数计算&#xff0c;一种是基于性能优化的通过移位的整数计算。浮点数计算公式为&#xff1a; gray 0.1140 * B 0.5870 * G 0.2989 * R;整数计算公式为&#xff1…

CYQ.Data 数据框架系列索引

2019独角兽企业重金招聘Python工程师标准>>> 索引基础导航&#xff1a; 1&#xff1a;下载地址&#xff1a;http://www.cyqdata.com/download/article-detail-426 2&#xff1a;入门教程&#xff1a;http://www.cyqdata.com/cyqdata/article-cate-33 3&#xff1a;购…

Tesseract 3 语言数据的训练方法

OCR,光学字符识别 光学字符识别(OCR,Optical Character Recognition)是指对文本资料进行扫描&#xff0c;然后对图像文件进行分析处理&#xff0c;获取文字及版面信息的过程。OCR技术非常专业&#xff0c;一般多是印刷、打印行业的从业人员使用&#xff0c;可以快速的将纸质资料…

Windows C++中__declspec(dllexport)的使用

__declspec是Microsoft VC中专用的关键字&#xff0c;它配合着一些属性可以对标准C/C进行扩充。__declspec关键字应该出现在声明的前面。 __declspec(dllexport)用于Windows中的动态库中&#xff0c;声明导出函数、类、对象等供外面调用&#xff0c;省略给出.def文件。即将函数…

图灵奖得主LeCun力推无监督学习:要重视基于能量的学习方法

作者 | Tiernan Ray译者 | 夕颜出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09;导语&#xff1a;图灵奖得主深度学习大牛 Yann LeCun 表示&#xff0c;人工智能的下一个发展方向可能是放弃深度学习的所有概率技巧&#xff0c;转而掌握一系列转移能量值的方法。据说&a…

html5小游戏Untangle

2019独角兽企业重金招聘Python工程师标准>>> 今天介绍一个HTML5的小游戏&#xff0c;让大家体验到HTML5带来的乐趣。这个小游戏很简单&#xff0c;只要用鼠标拖动 蓝点&#xff0c;让图上的所有线都不相交&#xff0c;游戏时间就会停止&#xff0c;是动用大家头脑的…

【VMCloud云平台】SCCM(四)域内推送代理

继上一篇云平台完成SCCM部署篇之后&#xff0c;SCCM篇正式开始&#xff0c;今天将开始介绍SCCM为域内机器推送代理&#xff08;紫色为完成实施&#xff0c;红色为实施中&#xff09;&#xff1a; 1、 点击站点&#xff1a; 2、 右键属性&#xff0c;点击客户端安装设置&#…