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

C++中extern C的使用相关推荐

  1. C++中extern使用

    C++中extern是指全局的意思.它一般有两个方面的用途: 1.声明变量 首先说一下声明和定义的区别: ①变量的定义:用于为变量分配存储空间,还可以为变量指定初始值.在一个程序中,变量有且仅有一个定 ...

  2. C/C++中extern关键字详解

    1 基本解释 :extern可以置于变量或者函数 前,以标示变量或者函数的定义在别的文件中 ,提示编译器遇到此变量和函数时在其他模块中寻找其定义 .此外extern也可用来进行链接指定. 也就是说ex ...

  3. C++中extern “C”含义深层探索(zz)

    1.引言 C++语言的创建初衷是"a better C",但是这并不意味着C++中类似C语言的全局变量和函数所采用的编译和连接方式与C语言完全相同.作为一种欲与C兼容的语言,C++ ...

  4. Re: Programming C/C++中extern C含义深层探索

    1.引言 C++语言的创建初衷是"a better C",但是这并不意味着C++中类似C 语言的全局变量和函数所采用的编译和连接方式与C 语言完全相同.作为一种欲与C 兼容的语言, ...

  5. C/C++中extern关键字详解与应用

    1.引言:多文件结构中,对全局变量(global variance)的体会 全局变量的好处是毋庸置疑的.方便在各个子模块和局部域中使用.所以,全局变量很适合做众多模块之间的公共交流与通信. 在单文件结 ...

  6. C/C++中extern的用法 ?

    C/C++中extern的用法 简介 extern修饰变量的声明. extern修饰函数声明. 使用extern和包含头文件来引用函数有什么区别呢? extern修饰符可用于指示C或者C++函数的调用 ...

  7. C++中extern “C”含义深层探索

    1.引言 C++语言的创建初衷是"a better C",但是这并不意味着C++中类似C语言的全局变量和函数所采用的编译和连接方式与C语言完全相同.作为一种欲与C兼容的语言,C++ ...

  8. C/C++中extern关键字详解[zz]

    1 基本解释:extern可以置于变量或者函数前,以标示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义.此外extern也可用来进行链接指定. 也就是说extern ...

  9. C++中extern关键字使用 http://blog.csdn.net/sruru/article/details/7951019

    C++中extern关键字使用 分类: C++ 语法 2012-09-06 15:37 327人阅读 评论(0) 收藏 举报 c++编译器 chapter 1 . extern关键字的作用 exter ...

  10. [转]C++中extern C的含义

    注:本文来自Internet.原文作者已无从考证.若您是原文作者,请给出具体的证明后,我将及时标明作者及出处. 1.引言 C++语言的创建初衷是"a better C",但是这并不 ...

最新文章

  1. 对Linux0.11 中 进程0 和 进程1分析
  2. postman接口测试实例_postman接口测试实例
  3. 计算机桌面是是在哪个盘,电脑虚拟内存是设置在哪个盘的
  4. 如何更好的解决问题 : The puzzle of die
  5. STIMULUS(二) —— Hello, Stimulus
  6. leetcode 1423. 可获得的最大点数(滑动窗口)
  7. 学习MySQL / MariaDB初学者 - 第1部分
  8. 记录Linux下彻底删除MySQL以及启动MySQL之后使用密码登录提示报ERROR 1045 (28000): Access denied for user ‘root‘@‘localhost
  9. kernel编译设置分区等功能
  10. python字典和json字符串相互转化的方法_Python处理json字符串转化为字典的简单实现...
  11. 剑指Offer值数字在排序数组中出现的次数
  12. Git合并特定commits 到另一个分支
  13. mac的一些使用事项
  14. oracle面试上机题,Oracle面试题附带答案
  15. The processing instruction target matching [xX][mM][lL] is not allowed.
  16. 百度文库刷财富值软件,如何刷百度文库财富值
  17. 【时空序列】使用3D卷积网络学习时空特征
  18. python画长方形的代码_python使用turtle画一个三角形、正方形(矩形或四边形)
  19. iOS端实现节日换肤
  20. html的hsl形式的颜色选择器,简单的HSL颜色选择器/拾色器

热门文章

  1. C++:随笔8---命名空间
  2. Python Qt GUI设计:QPrinter打印图片类(基础篇—21)
  3. 优达学城《DeepLearning》项目1:预测每日自行车租赁客流量
  4. C/C++数组初始化的一些误区
  5. linux sort 源码_Linux: 史上最全的sort命令案例,打包带走吧
  6. raymarching算法
  7. CDN和Web Cache领域相关的经典书籍推荐
  8. 绘制你的世界:探索构图和真实的深度感
  9. 高并发系统搭建:web负载均衡
  10. 探讨UnsupportedOperationException的原因及解决方案