dll导出函数的两种方式的比较
最初的网页链接已经挂了, 在此贴一个中间的转载链接
https://blog.csdn.net/zhazhiqiang/article/details/51577523
一 概要
vs中导出 dll的方法有两种: 一种是使用__declspec(dllexport), 另一种就是使用.def文件方式,
这两种方式的最主要区别是在导出函数的名字上, 其次还有一些操作的灵活性上以及功能的强弱
二 一个具体的例子
1 __declspec(dllexport) 方式
首先对C和C++编译(extern "C")与调用约定(__cdecl、__stdcall、__fastcall)进行组合测试:
<1> C++编译
__declspec(dllexport) int add(int, int);

__declspec(dllexport) int __cdecl add(int, int);

__declspec(dllexport) int __stdcall add(int, int);

__declspec(dllexport) int __fastcall add(int, int);

对于C++编译器的函数名修饰规则:不管__cdecl, __fastcall还是__stdcall调用方式,函数修饰名都是以"?"开始,后面是函数在名字,再后面是函数返回类型和参数类型按照代号拼出的参数表。对于__stdcall方式,参数表的开始标示是"@@YG”,对于__cdecl方式则是"@@YA”,对于__fastcall方式则是"@@YI”.
参数表后以"@Z”标示整个名字的结束,如果该函数无参数,则以"Z”标识结束。
<2> C编译
extern "C" __declspec(dllexport) int add(int, int);

extern "C" __declspec(dllexport) int __cdecl add(int, int);

extern "C" __declspec(dllexport) int __stdcall add(int, int);

extern "C" __declspec(dllexport) int __fastcall add(int, int);

<3> 备注
__declspec(dllexport)的位置:
To export functions, the __declspec(dllexport) keyword must appear to the left of the calling-convention keyword, if a keyword is specified.
For example:
__declspec(dllexport) void __cdecl Function1(void);
To export all of the public data members and member functions in a class, the keyword must appear to the left of the class name as follows:
class __declspec(dllexport) CExampleExport : public CObject
{ class definition };
2 def文件导出方式(项目中添加一个def后缀的文件, 然后在项目属性->连接器->所有选项->模块定义文件)
具体到测试实例,我们的def文件内容如下:
LIBRARY "win"
EXPORTS
add @1
其中LIBRARY指定dll的模块名称,即dll名字,EXPORTS后的每一行指定一个导出函数名字,这个名字和头文件中的声明一致,后面可以跟@序号指定该函数的序号(这个是可选的,后面按序号导入函数的时候再详细说)。
然后再测试一下__stdcall和__fastcall是否会对导出函数改名,测试结果如下,均未改名:
extern "C" int __stdcall add();

extern "C" int __fastcall add();

另外一种方案是在代码中给链接器指定导出函数名字:
extern "C" __declspec(dllexport) int __fastcall add(int a, int b);
#pragma comment(linker, "/export:add=@add@8")
这里告诉链接器,导出一个函数名为add的函数,函数入口点和@add@8相同

这样,我们既可以使用add,也可以使用@add@8了。
__stdcall方式和这类似,为add=_add@8。
【按序号而不是按名称从dll导出函数】
http://msdn.microsoft.com/zh-cn/library/e7tsx612%28VS.80%29.aspx
def文件定义如下:
LIBRARY "win"
EXPORTS
add @1 NONAME

函数名称和Hint都不见了。
这样也可以用来隐藏dll中一些重要函数。
隐藏了函数名称,在应用程序中使用序号来导入函数:
#include <windows.h>
#include <stdio.h>
int main()
{
typedef int (* AddFunc)(int, int);
HMODULE hModule = LoadLibrary("dll.dll");
AddFunc add = (AddFunc)GetProcAddress(hModule, MAKEINTRESOURCE(1)); //注意这里序号的指定方式
printf("%d\n", add(1, 2));
return 0;
}
三 总结:
1 __declspec(dllexport)
若要输出类的所有成员:数据or函数,__declspec(dllexport)要放在类名左边声明:
class __declspec(dllexport) Class1{}
如果类没有数据成员,__declspec(dllexport)放在class关键字前声明就会被编译器忽略,就没有lib生成,如下:
__declspec(dllexport) class Class1{}
使用 __declspec(dllexport) 非常方便,因为不必考虑维护 .def 文件和获取导出函数的修饰名。例如,如果您设计的 DLL 供自己控制的应用程序使用,则此方法很适用。如果通过新的导出函数重新生成 DLL,还必须重新生成应用程序,因为如果使用不同版本的编译器进行重新编译,则导出的 C++ 函数的修饰名可能会发生变化。
使用 .DEF 文件的优缺点(zz)
在 .def 文件中导出函数使您得以控制导出序号。当将附加的导出函数添加到 DLL 时,可以给它们分配更高的序号值(高于任何其他导出函数)。当您进行此操作时,使用隐式链接的应用程序不必与包含新函数的新导入库重新链接。这非常重要,例如,在设计将由许多应用程序使用的第三方DLL 时。可以通过添加附加功能不断地增强 DLL,同时确保现有应用程序继续正常使用新的 DLL。MFC DLL 是使用 .def 文件生成的。
DLL 的 .def 文件中的导出名相匹配。
dll导出函数的两种方式的比较的更多相关文章
- (转)DLL中导出函数的两种方式(dllexport与.def文件)
DLL中导出函数的两种方式(dllexport与.def文件)http://www.cnblogs.com/enterBeijingThreetimes/archive/2010/08/04/1792 ...
- 【转】DLL中导出函数的两种方式(dllexport与.def文件)
DLL中导出函数的两种方式(dllexport与.def文件) DLL中导出函数的声明有两种方式: 一种方式是:在函数声明中加上__declspec(dllexport):另外一种方式是:采用模块定义 ...
- DLL中导出函数的两种方式(dllexport与.def文件)
DLL中导出函数的声明有两种方式: 一种方式是:在函数声明中加上__declspec(dllexport): 另外一种方式是:采用模块定义(.def)文件声明,(.def)文件为链接器提供了有关被链接 ...
- DLL声明导出函数的两种方式
DLL中导出函数的声明有两种方式:一种为在函数声明中加上__declspec(dllexport):另外一种方式是采用模块定义(.def) 文件声明,.def文件为链接器提供了有关被链接程序的导出.属 ...
- C++ DLL导出函数的两种方法(导出序号那种方法,别人看不到函数名)
第一种就直接导出函数名如下代码: #ifdef__cplusplus #define TEXPORT extern "c" _declspec(dllexport) #dlse # ...
- C#调用C++ DLL动态库的两种方式
第一种方式:C++导出函数, c#dllimport 的方式 在很多地方都看到过,如[dllimport "user32.dll"]这种代码,调用windows API,就是通过这 ...
- vue项目中导出PDF的两种方式
参考大家导出的方式,基本上是如下两种: 1.使用 html2Canvas + jsPDF 导出PDF, 这种方式什么都好,就是下载的pdf太模糊了.对要求好的pdf这种方式真是不行啊! 2.调用浏览器 ...
- JS定义函数的两种方式:函数声明和函数表达式
函数声明 关于函数声明的方式,它的一个重要的特性就是函数声明提升(function declaration hoisting),意思是在执行代码之前会先读取函数声明.这就意味着可以把函数声明放在调用它 ...
- JS调用函数的两种方式
<script type="text/javascript"> window.onload = init; //onload 表示页面全部加载完毕后,再调用init() ...
随机推荐
- soapUI的安装及破解
1.下载安装包 SoapUI SoapUI-Pro-x64-5.1.2.exe Protection-4.6.jar scz.key 2.安装SoapUI-Pro-x64-5.1.2.exe 3.拷贝 ...
- html+jquery实现简单图片裁剪
有了上一篇图片放大镜的铺垫,今天的这个例子是缩小镜,因为裁剪的原图往往很大,不能在工作区域看到全部图片,所以,要有缩小镜来显示,当前裁剪的区域是原图的个部分.按照惯例首先看下效果图: 功能一:载入默认 ...
- office2013 Word 缺少校对工具,按提示下载、安装了文件还是不成功的解决方案
找到你的office安装源iso镜像加载 ——点开镜像双击setup.exe ——选择添加或删除功能 ——下一步——其他的不要动,展开office共享功能项 ——找到校对工具点出下拉项(点朝下的黑色箭 ...
- 64位ubuntu16.04系统安装tensorflow_cpu
ubuntu16.04安装tensorflow_cpu 一.安装anaconda: ①.下载anaconda包:Anaconda3-5.2.0-Linux-x86_64.sh 这是python3.6. ...
- JDK无法卸载问题解决
在控制面板卸载JDK时,显示正在收集删除文件,进度条满了之后就闪退了,但JDK还在,试了几次都是如此. 后来,发现微软官方出了“修复阻止程序安装或删除的问题”的应用,可以自动修复包括阻止你安装或删除程 ...
- python numpy模块使用笔记(更新)
np.arange(int a) 生成一个一维array,元素个数是a个,元素是0到a-1 注意arange不能直接生成多维array np.arange(int a).reshape(int b,i ...
- myBatis---接口代理开发(demo)
一.概述 使用接口代理开发,可以不用写接口的实现类,而采用的是MapperFactoryBean代理的实现类. * 接口代理方式开发,遵循四大原则 * 1.方法名 == mapper.xml的id名 ...
- 企业SQL笔试
Student(SID, Sname, Sage, Ssex) 学生表 Course(CID, Cname, TID) 课程表 SC(SID, CID, score) 成绩 ...
- 链路聚合trunk实现
用户需求 1,在原有网络基础上实现用户接入Internet 2,监控摄像头不改变原有功能 配置思路 1,首先确定接入交换机是否为管理型交换机 2, 确认接入交换机管理IP 3,划分Vlan 创建tr ...
- JavaMap的一些常用方法
package exam; import java.util.Collection; import java.util.HashMap; import java.util.Map; import ja ...