dll函数生成规则
所谓名字修饰约定,就是指变量名、函数名等经过编译后重新输出名称的规则。
比如源代码中函数名称为int Func(int a,int b),经过编译后名称可能为?Func@@YAHHH@Z、?Func@@YGHHH@Z、_Func@8,也有可能与源代码中名称相同为Func。
影响编译后输出的名称通常与名字修饰约定(extern "C"、extern "C++"等)和函数调用约定(__stdcall、__cdecl等)等相关。
口说千遍,不如实际演练一遍。那么,就让我们写代码来测试下。
注意,本文只讨论extern "C"、extern "C++"和__stdcall、__cdecl相关的约定,其他约定不在本文讨论范围内。另外,编译的环境为XP + VC++6.0SP6。
首先,用C方式导出两个函数:
Dll1.c
- _declspec(dllexport) int __cdecl Func_cdecl(int a,int b)
- {
- return 1;
- }
- _declspec(dllexport) int __stdcall Func_stdcall(int a,int b)
- {
- return 1;
- }
导出的两个函数名为:
再以C++方式导出:
Dll1.cpp
- _declspec(dllexport) int __cdecl Func_cdecl(int a,int b)
- {
- return 1;
- }
- _declspec(dllexport) int __stdcall Func_stdcall(int a,int b)
- {
- return 1;
- }
导出结果如下:
然后,我们再以C++方式导出如下代码中的函数:
- extern "C" _declspec(dllexport) int __stdcall Func_C_stdcall(int a,int b)
- {
- return 1;
- }
- extern "C++" _declspec(dllexport) int __stdcall Func_CPP_stdcall(int a,int b)
- {
- return 1;
- }
- extern "C" _declspec(dllexport) int __cdecl Func_C_cdecl(int a,int b)
- {
- return 1;
- }
- extern "C++" _declspec(dllexport) int __cdecl Func_CPP_cdecl(int a,int b)
- {
- return 1;
- }
导出结果如下:
有了以上实验结果,我们再结合以下名字输出规则进行理解:
- C方式编译(extern "C"):
- __stdcall调用约定:输出名称在原名称前加一下划线,后面再加上一个“@”和其参数的总字节数(_原名称@参数总字节数),如名称int Func_C_stdcall(int a,int b)输出为_Func_C_stdcall@8;
- __cdecl调用约定:与原名称相同,如名称int Func_C_cdecl(int a,int b)输出还是为Func_C_cdecl;
- C++方式编译(extern "C++"):
- __stdcall调用约定:
- 输出名称以“?”开始,后跟原名称;
- 原名称后再跟“@@YG”,后面再跟返回值代号和参数表代号,代号表示如下:
X--void ,
D--char,
E--unsigned char,
F--short,
H--int,
I--unsigned int,
J--long,
K--unsigned long,
M--float,
N--double,
_N--bool,
...
PA--表示指针,后面的代号表明指针类型,如果相同类型的指针连续出现,以“0”代替,一个“0”代表一次重复; - 参数表后以“@Z”标识整个名字的结束,如果该函数无参数,则以“Z”标识结束。如名称int Func_CPP_stdcall(int a,int b)编译后的输出名称为?Func_CPP_stdcall@@YGHHH@Z。
- __cdecl调用约定:与_stdcall调用约定基本一致,只是参数表的开始标识由上面的“@@YG”变为“@@YA”。如名称int Func_CPP_cdecl(int a,int b)编译后输出名称为?Func_CPP_cdecl@@YAHHH@Z。
- __stdcall调用约定:
有个这个规则,再回头去看我们的实验结果,就很好理解了。
当然,编译C文件和编译CPP文件,不需加extern "C"和extern "C++",因为编译C文件当然默认的是extern "C",而编译CPP文件则默认的是extern "C++"。
现在我们也能理解为什么导出DLL时通常需要加上extern "C"。试想,如果一个C++导出的dll,没有加extern "C",则导出的名称为extern "C++"约定下的名称。如果这个dll需要提供给用C编写的程序使用,那么这个程序是无法调用这个dll的,因为C写的程序遵循的是extern "C"约定,链接时链接器将按照extern "C"约定的名称去寻找外部名称,这当然找不到,因为dll中的输出名称为extern "C++"约定下的名称。
dll函数生成规则的更多相关文章
- [转载]DLL命名规则
程序集是一个部署单元,同时还代表托管代码程序的身份.一般来说一个程序集仅与一个DLL相对应.本节主要讲DLL命名约定,程序集的命名约定与此类似. 要记住,名字空间与DLL和程序集是不同的概念.名字空间 ...
- MFC的规则DLL与扩展DLL
一.MFC规则DLL MFC规则DLL可以在该dll内部使用MFC,但是与应用程序的接口不能是MFC的.能够被所有支持dll的编程语言所写的应用程序使用,当然也包括使用MFC创建的应用程序.在 ...
- VC++动态链接库(DLL)编程深入浅出(zz)
VC++动态链接库(DLL)编程深入浅出(zz) 1.概论 先来阐述一下DLL(Dynamic Linkable Library)的概念,你可以简单的把DLL看成一种仓库,它提供给你一些可以直接拿来用 ...
- VS2010 C++环境下DLL和LIB文件目录及名称修改
VS2010 C++环境下DLL和LIB文件目录及名称修改 转自:http://blog.csdn.net/archielau/article/details/8507581 DLL工程,Debug版 ...
- AFX_MANAGE_STATE(AfxGetStaticModuleState())DLL导出函数包含MFC资源
AFX_MANAGE_STATE(AfxGetStaticModuleState()) 先看一个例子: .创建一个动态链接到MFC DLL的规则DLL,其内部包含一个对话框资源.指定该对话框ID如下: ...
- VC++制作DLL详解
1. DLL的基本概念 应用程序(exe)要引用目标代码(.obj)外部的函数时,有两种实现途径——静态链接和动态链接. 1. 静态链接 链接程序搜索对应的库文件(.lib),然后将这个对 ...
- VC++制作DLL具体解释
1. DLL的基本概念 应用程序(exe)要引用目标代码(.obj)外部的函数时,有两种实现途径--静态链接和动态链接. 1. 静态链接 链接程序搜索相应的库文件(.lib),然后将这个对 ...
- VC中不同类型DLL及区别
1. DLL的概念可以向程序提供一些函数.变量或类. 静态链接库与动态链接库的区别:(1)静态链接库与动态链接库都是共享代码的方式.静态链接库把最后的指令都包含在最终生成的EXE文件中了:动态链接库不 ...
- dll的概念 dll导出变量 函数 类
1. DLL的概念 DLL(Dynamic Linkable Library),动态链接库,可以向程序提供一些函数.变量或类.这些可以直接拿来使用. 静态链接库与动态链接库的区别: (1)静态链接 ...
随机推荐
- sed详解---用法及解释
1.sed -n '2'p filename 打印文件的第二行. 2.sed -n '1,3'p filename 打印文件的1到3行 3. sed -n '/Neave/'p filename 打印 ...
- 理解加密算法——创建CA机构,签发证书并开始TLS通信
1 不安全的TCP通信 普通的TCP通信数据是明文传输的,所以存在数据泄露和被篡改的风险,我们可以写一段测试代码试验一下,NODE.JS代码: TCP Server: const net=requir ...
- erlang里面中文相关处理
在控制台输出的话 Name = "测试数据", io:format("~ts~n",[Name]). 如果是和客户端通信,假如都是utf8编码 服务器获取的时候 ...
- 【学习记录】二分查找的C++实现,代码逐步优化
二分查找的思想很简单,它是针对于有序数组的,相当于数组(设为int a[N])排成一颗二叉平衡树(左子节点<=父节点<=右子节点),然后从根节点(对应数组下标a[N/2])开始判断,若值& ...
- centos7 yum 安装mysql
介绍在CentOS7上yum安装数据库服务器MySQL Community Server 5.7的方法. 准备 CentOS7默认安装了和MySQL有兼容性的MariaDB数据库,在我们安装MySQL ...
- 转:mysql加锁处理分析
MySQL/InnoDB的加锁分析,一直是一个比较困难的话题.我在工作过程中,经常会有同事咨询这方面的问题.同时,微博上也经常会收到MySQL锁相关的私信,让我帮助解决一些死锁的问题.本文,准备就My ...
- 《C++ Primer》读书笔记
在C++中,基类必须指出希望派生类重新定义哪些函数,定义为virtual的函数是基类期待派生类重新定义的,基类希望派生类继承的函数不能定义为虚函数. 引用和指针的静态类型与动态类型可以不同,这是C++ ...
- python学习(二十) Python 中的比较:is 与 ==
Python 中的比较:is 与 == 在 Python 中会用到对象之间比较,可以用 ==,也可以用 is .但是它们的区别是什么呢? is 比较的是两个实例对象是不是完全相同,它们是不是同一个对象 ...
- 大白话系列之C#委托与事件讲解大结局
声明:本系列非原创,因为太精彩才转载,如有侵权请通知删除,原文:http://www.cnblogs.com/wudiwushen/archive/2010/04/20/1698795.html 今天 ...
- video2gift环境安装(Theano等)
pip install Theano http://deeplearning.net/software/theano/install_centos6.html pip install moviepy ...