extern C的思考
背景
C语言和C++有着千丝万缕的联系,C++的另外一个名称是C With Class。同时差异也是有的。
C语言不支持重载函数,因为C语言编译器编译出来的函数在符号表中的标识符即为函数名本身(这里以VisualStudio2015
为例),支持重载函数意味着它们在符号表中的标识符是一样的,也就无法对他们进行区分。
C++支持重载函数,是因为C++编译器编译出来的函数在符号表中的标识符包含了参数的信息。我们知道重载函数本来就是靠参数的不同(参数个数与参数类型不同)来区分不同的函数,所以包括参数信息的标识符也就可以被分区开了。
担忧
如果C++中需要调用由C语言编译器编译出的动态库中的函数,该函数在C++中编译出的符号表中的标识带有参数信息,而其在动态库又不带参数信息,因此就会在链接时报错找不到该符号。
解决
我们可以使用extern "C"来声明使用的动态库中的函数:
extern "C" FunctionInDll();
...
// 调用FunctionInDll()
这样,C++编译器就会以C语言的方式来生成函数在符号表中的标识符,就和动态库中的标识符保持一致了。
案例
有如下VisualStudio2015
动态库工程TestDll
,其中包含两个文件:algorithm.h
、algorithm.cpp
。
algorithm.h
#pragma once__declspec(dllexport) int Add(int a, int b);
__declspec(dllexport) int Minus(int a, int b);
extern "C" __declspec(dllexport) int Multiply(int a, int b);
extern "C" __declspec(dllexport) int Devide(int a, int b);// 也可以使用如下的声明方式
//extern "C"
//{// __declspec(dllexport) int Multiply(int a, int b);
// __declspec(dllexport) int Devide(int a, int b);
//}
algorithm.cpp
#include "algorithm.h"int Add(int a, int b)
{return (a + b);
}int Minus(int a, int b)
{return (a - b);
}int Multiply(int a, int b)
{return a * b;
}int Devide(int a, int b)
{return a / b;
}
Multiply()
和Devide()
使用extern "C"
进行声明,编译工程,然后使用Dependency Walker.exe
打开生成的动态库TestDll.dll
:
可以看到使用和不使用extern "C"
进行声明生成的标识符的明显区别。
另外,可以测试下C语言中尝试编写重载函数的实际效果:在algorithm.h中
添加:
extern "C" __declspec(dllexport) int Devide(int a, int b, int c);
编译工程直接报错如下:不允许重载函数的第二个 C 链接。
1>------ 已启动全部重新生成: 项目: TestDll, 配置: Debug Win32 ------
1> algorithm.cpp
1>d:\vsproject\testdll\testdll\algorithm.h(7): error C2733: “Devide”: 不允许重载函数的第二个 C 链接
1> d:\vsproject\testdll\testdll\algorithm.h(6): note: 参见“Devide”的声明
========== 全部重新生成: 成功 0 个,失败 1 个,跳过 0 个 ==========
extern C的思考相关推荐
- 关于#define/extern/static的思考与总结
写在前面 全局常量作为开发人员一定是一个比较熟悉的概念.全局常量的写法自然也比较多,最近在进行项目的常量重构时看到了各种各样的写法,其中宏定义占大部分,然而有很多使用宏定义是不规范的,而且宏定义只是在 ...
- 《c语言修炼内功之第二种境界(看代码就是内存)之关键字系列二》
前言:这个系列内容我会深入讲解一下c语言中的重点内容,会把每一个知识点讲的更加底层些,会增强大家的c语言内功,从内存维度看代码你会有不同的理解. 这一节我主要讲一下多文件的知识,static修饰全局变 ...
- 嵌入在C++程序中的extern C
1.extern的作用 extern是C/C++语言中表明函数和全局变量作用范围(可见性)的关键字,可以告知编译器,用extern声明的函数和变量可以在本模块或其它模块中使用. 通常,在模块的头文件中 ...
- 何时在C ++中使用extern
本文翻译自:When to use extern in C++ I'm reading "Think in C++" and it just introduced the exte ...
- C++中extern “C”含义深层探索(zz)
1.引言 C++语言的创建初衷是"a better C",但是这并不意味着C++中类似C语言的全局变量和函数所采用的编译和连接方式与C语言完全相同.作为一种欲与C兼容的语言,C++ ...
- Re: Programming C/C++中extern C含义深层探索
1.引言 C++语言的创建初衷是"a better C",但是这并不意味着C++中类似C 语言的全局变量和函数所采用的编译和连接方式与C 语言完全相同.作为一种欲与C 兼容的语言, ...
- 揭密 extern C
1.引言 C++语言的创建初衷是"a better C",但是这并不意味着C++中类似C语言的全局变量和函数所采用的编译和连接方式与C语言完全相同.作为一种欲与C兼容的语言,C++ ...
- extern C的用法解析
extern "C"的用法解析 2012-03-20 23:29 by Rollen Holt, 20231 阅读, 6 评论, 收藏, 编辑 1.引言 C++语言的创建初衷是&q ...
- C/C++混合编程——extern C
1.引言 C++语言的创建初衷是"a better C",但是这并不意味着C++中类似C语言的全局变量和函数所采用的编译和连接方式与C语言完全相同.作为一种欲与C兼容的语言,C++ ...
- C++中extern “C”含义深层探索
1.引言 C++语言的创建初衷是"a better C",但是这并不意味着C++中类似C语言的全局变量和函数所采用的编译和连接方式与C语言完全相同.作为一种欲与C兼容的语言,C++ ...
最新文章
- 关于亿级账户数据迁移,你应该试试这种方法...
- Swift3.0语言教程获取字符串长度
- 史陶比尔与机器人之父
- api接口返回动态的json格式?我太难了,尝试一下 linq to json
- 使用stanford nlp进行依存句法分析
- Java导出Highcharts需要的3个外部jar包
- Java类加载文章2(z)
- [日志]08/19/2007
- 027. 从从门槛和可复制性聊聊生意模式
- 计算机怎样同时运行多个程序的?进程相关概念介绍
- 医疗器械软件网络安全相关
- PLC脆弱性评估及相应解决方案
- 【中学教师资格证-教育知识与能力】简答题
- 结构方程模型(SEM)及其R实现
- 虚拟机命令里面的光标不动了怎么办_Linux 11个炫酷的终端命令!你知道几个?
- 成三棋、九子棋、十二子棋
- 《密码编码学与网络安全》复习总结
- excel解析工具类
- 蚂蚁金服如何开垦农村金融市场
- configure: error: C compiler cc is not found
热门文章
- 别了MongoDB?
- 《学习opencv》笔记——关于一些画图的函数
- 老男孩教育每日一题-第106天-MySQL如何授权用户admin:password远程访问权限
- jQuery直接调用asp.net后台WebMethod方法
- 十个必备的学习iOS开发的网站
- td中使用overflow:hidden; 无效解决方案
- 无法创建新虚拟机: 无法打开配置文件“E:\vmware\Windows7.vmx”: 拒绝访问。
- 1.创建一个 Slim 应用
- 3. 安装 phpmyadmin
- [Bzoj1143][CTSC2008]祭祀river