该文章讲述了dll的基本知识、dll的工程建立和使用dll两种方式实现在应用程序中使用dll的导出函数。
一、DLL的简单介绍
1. DLL定义
DLL(Dynamic Link Library)文件为动态链接库文件,又称“应用程序拓展”,是软件文件类型。在Windows中,许多应用程序并不是一个完整的可执行文件,它们被分割成一些相对独立的动态链接库,即DLL文件,放置于系统中。当我们执行某一个程序时,相应的DLL文件就会被调用。一个应用程序可使用多个DLL文件,一个DLL文件也可能被不同的应用程序使用,这样的DLL文件被称为共享DLL文件。[引用百度百科]
2. DLL特点
由DLL定义可知,DLL特点有:
1)扩展了应用程序的特性。DLL可以被动态地载入到进程的地址空间中。
2)简化了项目管理,可以让不同的开发团队管理不同的模块。
3)有助于节省内存。一个dll可被多个程序共享。多个程序调用同一个dll内的同一个函数时,系统却只需将该dll加载一次。
4)促进资源共享。
5)促进了本地化。可以使应用程序只包含代码但不包含用户界面组件。
6)有助于解决平台间差异。使用延迟加载机制,程序仅仅加载需要的函数,使程序可以在老版本的系统中运行,可不是在某些函数不被兼容时拒绝运行。
7)可以用于特殊目的。如钩子函数等等。
3. DLL的标准搜索路径
1)可执行文件目录。
2)windows系统目录。
3)windows目录的System目录。
4)windows目录。
5)进程当前目录。
6)PATH环境变量所列出的目录。
4. DLL加载方式
DLL加载方式有隐式链接(需要.dll,.lib,.h)和显式链接(需要.dll)。隐式链接就是在程序开始执行时就将DLL文件加载到内存当中,而显示链接,是实时加载,程序需要的时候加载,不需要的时候,卸载。只要没有在程序中显式链接的,都是隐式链接。
·隐式链接(静态链接)中,由编译系统完成对DLL的加载和应用程序结束时DLL的卸载。
·显示链接(动态链接)中,由编程者用API函数加载和卸载DLL(DLL加载—DLL函数地址获取—DLL释放)方式
1)隐式链接(需要.dll,.lib,.h)
a。将dll工程下的dll和lib文件拷到测试工程下
b。同时编写头文件.h【头文件书写导入函数】
//_declspec(dllimport)说明函数为导入函数
extern "C" _declspec(dllimport) int Max(int a, int b);
extern "C" _declspec(dllimport) int Min(int a, int b);
c。编写实现文件.cpp
#include "test.h"
#include <iostream>
using namespace std;
// 可写全路径
#pragma comment(lib,"TestDLL001.lib")
int main()
{
int a=Min(3,4);
cout<<a<<endl;
system("pause");
return 0;
}
---------------------
作者:red10057
来源:优快云
原文:https://blog.youkuaiyun.com/red10057/article/details/7394213
.lib文件对应的搜索路径如下:
1、项目当前目录.cpp目录(项目和解决方案的Debug不行)(也不是解决方案目录)
2、VC设置中的库目录(Library Directories)
3、如果lib库不放到搜索路径中,也可以在程序中添加:
#pragma comment(lib,"D:/DLLTest.lib")//若是相对路径,则为项目当前.cpp目录
2)显式链接(需要.dll)【必须在生成该dll文件时 extern "C"】
a。将dll工程下的dll文件拷贝到测试工程下
b。编写实现文件.cpp
#include <Windows.h> // 包含 HINSTANCE
#include <iostream>
using namespace std;
int main()
{
// 必须在生成该dll文件时 extern "C";
HINSTANCE his = LoadLibraryA("TestDLL001.dll"); //用于加载dll
typedef int(*pmin)(int a, int b);
pmin mmi=(pmin)GetProcAddress(his, "Min"); //GetProcAddress()用于获得函数地址
// !!!这是要通过函数名得到对应函数地址后才可以调用该函数操作,与静态链接方式相比,感觉有点麻烦
// 尝试一下是否可以有其他方式调用
int aa=mmi(3,4);
cout<<aa<<endl;
FreeLibrary(his); //释放dll
system("pause");
return 0;
}
---------------------
作者:red10057
来源:优快云
原文:https://blog.youkuaiyun.com/red10057/article/details/7394213
5. 个人理解
综上所述,我理解DLL类似一个模块,DLL里面包含了函数实现方式。不妨定义test.dll中包含函数add,当一个应用程序需要调用test.dll的add函数时,无需将add函数实现代码写进该exe的源代码中,可通过上述2种方式加载test.dll后直接调用该dll的add函数,这样其实也是实现了代码重用,假设add函数是很多个应用程序都要用的,无需将add函数代码写到这些应用程序的源代码中,只需将test.dll放到工作目录下即可。
二、第一个DLL程序
加入代码例子的讲解可以加深对DLL的认识~o( =∩ω∩= )m
如果看到这还是对DLL陌生,额,我觉得这是很正常的现象,因为当初我在学DLL时看了很多篇相关文章也是对DLL陌生,直到我写了第一个DLL程序,我才开始熟悉DLL,原来DLL是这回事呀~所以还是多撸代码吧٩(๑>◡<๑)۶
1. 新建一个DLL工程
实验环境:vs2008+win7 x64



至此,一个dll工程已经建立。其目录如下:

其中,dllmain.cpp是DLL程序入口点函数,其详细内容可见https://blog.youkuaiyun.com/Quellaaa/article/details/83992244
testDll.h和testDll.cpp文件用于声明和定义导出函数。

导出函数的声明方式:
1)一种在函数声明类型和函数名之间加上“_declspec(dllexport)”。
2)另外一种采用模块定义(.def)文件声明,需要在库工程中添加模块文件,格式如下:
LIBRARY 库工程名称
EXPORTS 导出函数名
2. 第一个DLL程序
第一个DLL程序用于实现导出函数,并在exe中使用~
(可用vs自带的dumpbin.exe查看导出函数表,使用方式请戳→https://blog.youkuaiyun.com/Quellaaa/article/details/81300449)

编译:


编译得到的结果:

查看testDll.dll的导出函数表:

由上图可知,成功将新增的两个函数导出。
接下来将dll运用到exe中:
1)静态链接
将该testDll.dll、testDll.lib和testDll.h文件放在exe工程目录下:

testUseDll.cpp代码:

执行结果如下:

2)动态链接
这里有个类,好像直接按上面讲述的动态链接方法走不通,emmm……先把普通函数的动态链接方式写了,类的动态链接研究学习后就写在另外一个博客啦~类的静态链接dll文件是没有问题哒~(o´ω`o)ノ
以extern "C"模式生成dll,即改为#define TESTDLL_API extern "C" __declspec(dllexport)
只需将生成的testDll.dll放入到工程目录下,testUseDll.cpp代码如下:
#include "stdafx.h"
#include <iostream>
#include <Windows.h>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
HINSTANCE hIs = LoadLibrary(_T("testDll.dll"));
typedef int (*fun)(int, int);
fun Add= (fun)GetProcAddress(hIs, "Add");
cout << Add(1, 2)<<endl;
return 0;
}
执行结果如下:

以上,就是这篇文章全部内容。若有不对之处,欢迎指正。(。⊙౪⊙。)
(ノ◕ω◕)ノ若对你有帮助,可以顶一下哟~XD
1169



被折叠的 条评论
为什么被折叠?



