DLL动态链接库的创建与使用
动态链接库英文为DLL,是Dynamic Link Library的缩写。DLL是一个包含可由多个程序,同时使用的代码和数据的库 --------------百度百科
下面我们使用vs2010创建一个可供win32程序使用的dll
- 打开vs2010,点击新建项目
- 新建一个win32项目
- 点击下一步
- 新建一个空的dll项目
- 右键源文件,添加,新建项
- 新建一个c文件
- 同样的在头文件里新建一个h文件
- 然后就可以开始写代码了
每一个dll都有一个入口函数,这个入口函数叫做 DLLMain
这个东西咱暂时用不到,就先不写了,如果你生成的是标准的dll文件,这个入口函数就会出现在你的源代码中。然后就可以开始写函数了,在写函数之前,先介绍一下dll中的规则
- 函数前面要加上修饰符 如__declspec(dllexport) 他的意思是 declear spece dll export 声明这是一个导出的dll函数。
- windows要求dll函数要加上修饰符CALLBACK (但这只是windows要求,dll要是不是给windows应用程序用的就不用加上这个)。
- 用extern "c"来表明使用c语言的规则解释函数
函数:
__declspec(dllexport) void GiaoWarningA() { MessageBoxA(NULL,"giao","warning",MB_OK); return; }
__declspec(dllexport) void GiaoWarningW() { MessageBoxW(NULL,L"giao",L"warning",MB_OK); return; } |
一般winapi中的函数都有两个版本,一个是ascii码版本,一个是unicode版本,windows使用宏来自动选择,例如
//编码判断 #ifdef UNICODE #define GiaoWarning GiaoWarningA
#else #define GiaoWarning GiaoWarningW
#endif |
我们也可以借鉴这种思想,来自动选择是否加上extern "C"
例如
//语言判断 #ifdef __cplusplus #define EXPORT extern "C" __declspec (dllexport) #else #define EXPORT __declspec (dllexport) #endif |
了解了这些我们就可以开始写我们的头文件了
头文件giao.h
//语言判断 #ifdef __cplusplus #define EXPORT extern "C" __declspec (dllexport) #else #define EXPORT __declspec (dllexport) #endif
//函数声明 EXPORT void CALLBACK GiaoWarningA(); EXPORT void CALLBACK GiaoWarningW();
//编码判断 #ifdef UNICODE #define GiaoWarning GiaoWarningA
#else #define GiaoWarning GiaoWarningW
#endif |
注意这三块代码我摆放的顺序
- 语言判断 声明了EXPORT宏
- 函数声明 使用了EXPORT宏
- 编码判断 使用函数名创建了统一函数名的宏
另外还有一点,在函数声明中EXPORT void CALLBACK的顺序可别弄乱了
这个CALLBACK是win32函数所需的,必须包含windows.h,
CALLBACK可以不用
EXPORT void CALLBACK GiaoWarningA(); |
源文件giao.c
#include "giao.h" #include <Windows.h>
EXPORT void CALLBACK GiaoWarningA() { MessageBoxA(NULL,"giao","warning",MB_OK); return; }
EXPORT void CALLBACK GiaoWarningW() { MessageBoxW(NULL,L"giao",L"warning",MB_OK); return; } |
源文件中的函数原型与头文件中的一毛一样
还有就是头文件中要包含giao.h和函数用到的头文件
- 然后右键项目,点击生成
- 右键giao点击打开所在的文件夹
- 返回到上一级目录
共有三个重要的文件 giao.h giao.lib giao.dll
- 进入这一级的Debug目录
- 然后就找到了全部的三个文件
- 如何使用动态链接库
使用动态链接库的方法有两种,一种是启动时加载,一种是运行时加载我们先来将如何在 启动时加载链接库
- 启动时加载链接库
我们依然还是新建一个win32项目
- 直接点击完成
- 右键打开项目所在文件夹
- 将之前的giao.h giao.lib giao.dll全都复制到这里
- 添加头文件 giao.h
- 添加链接库导入文件 giao.lib
注意lib和dll的名字是你dll项目的名字,而h文件的名字是你创建的时候指定的,不要弄混了,还有这里千万不要写成wdnmd.dll要不然会出错,而且编译器也发现不了。 - 开始使用
我是把函数放在WM_PAINT里了,你也可以放在其他地方,
- 运行结果
- 运行时加载动态链接库
我们会用到两个函数,LoadLibrary,GetProcAddress功能是加载动态链接库,获取函数地址
- 定义一个宏,创建两个变量
因为我们会用到函数地址,就要用函数指针来保存这个函数地址
而且因为我们要对GetProcAddress返回的地址进行强制类型转换,所以我们要定义一个宏来代替一个函数指针的类型还有一个实例句柄用来操作动态链接库
typedef void (*FUC)(); FUC fuc; HINSTANCE hlibrary; |
然后
hlibrary = LoadLibraryA("wdnmd.dll"); fuc = (FUC)GetProcAddress(hlibrary,"GiaoWarningA"); fuc(); |
这里我遇到了一些问题,GetProcAddress的返回值一直都是NULL,好像是函数名有问题。
找到了一些解决的方法,但也不是太好
关于__stdcall 导出的函数名为: _函数名@0 (0为参数所占的总字节数)
__fastcall 导出的函数名为: @函数名@0 (同上)
__cdel 导出的函数名为: 函数名
啥都不加 导出的函数名为: 函数名
windows要求的CALLBACK其实就是这个__stdcall,所以可以按照他的导出格式,去调用函数。如 fuc = (FUC)GetProcAddress(hlibrary,"_GiaoWarningA@0");