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() ...
随机推荐
- Nginx+Tomcat配置负载均衡-动静分离(二)
配置动静分离的时候遇到了一些问题,一个是配置nginx配置文件有问题导致访问不到服务器,另一个问题是配置静态资源的路径和实际的资源目录不匹配导致404,502等错误 结合上一篇的基础,在此将动静分离的 ...
- 【leetcode】492. Construct the Rectangle
problem 492. Construct the Rectangle 参考 1. Leetcode_492. Construct the Rectangle; 完
- redis的LRU算法(二)
前文再续,书接上一回.上次讲到redis的LRU算法,文章实在精妙,最近可能有机会用到其中的技巧,顺便将下半部翻译出来,实现的时候参考下. 搏击俱乐部的第一法则:用裸眼观测你的算法 Redis2.8的 ...
- 信号量及P/V操作
有一个厕所,允许多个男生同时使用,也允许一个女生使用,但是不允许男女共用(那岂不是乱了套)通过厕所门口有一个三面小牌子来运行.一面是男生在用,第二面是女生在用,第三面是空.运行机制:第一个进入空厕所男 ...
- [LeetCode&Python] Problem 415. Add Strings
Given two non-negative integers num1 and num2 represented as string, return the sum of num1 and num2 ...
- jq ajax数据交互
get 与 post 的区别 了解和使用 get和post是HTTP与服务器交互的方式, 说到方式,其实总共有四种:put,delete,post,get. 他们的作用分别是对服务器资源的增,删,改, ...
- 我对CSS的认识
花费了一段时间,终于对HTML有了一定的了解,随后又开始进行CSS的战斗感觉自己学起来有一点吃力.我就简单的讲一下我所学到的吧! CSS的概述. 层叠式样式表,用于控制网页样式并允许将样式信息并允许将 ...
- ssm项目导入activiti依赖后jsp页面el表达式报错
错误原因:Tomcat8.x与activiti6.0依赖冲突导致 解决方法: 1.修改tomcat版本 2.在pom.xml中修改 在依赖中把 <dependency> <group ...
- node中的事件发射器
在事件环中node通过on和emit进行事件的接收和发射,笔者以简单的窗口聊天小demo来演示一下如何通过事件环来发射和监听事件并执行回掉: var events=require('events') ...
- java web 登录后更新JSESSIONID
https://huangqiqing123.iteye.com/blog/2031455 登录前的请求一般都是http的,http是不安全的,假设用户登录前的JSESSIONID被人取得,如果登录后 ...