19.2 win32 DLL的创建和使用
1.VC++ 新建 Win32 Dynamic-Link Library类型的工程,选项 an empty dll project
2, 添加C++源文件 Dll.cpp, 编写代码,加法和减法
19.2.1 Dumpbin 命令
1,安装目录vc98\bin目录下, 执行dumpbin命令。如无法执行,运行vcvars32.bat这个批处理文件,建立环境信息
2,如果要查看一个DLL提供的导出函数,使用/exports选项来运行 dumpbin命令。 在DLL1.dll 文件所在目录下,输入下述命令并回车
Dumpbin -exports dll1.dll
19.2.2
为了让dll 导出一些函数,在需要被导出的函数前添加 _declspec(dllexport)
19.3隐式方式加载dll
19.3.1 利用 extern 声明函数
1,对库函数添加声明,extern 声明
2,将dll1.lib文件复制到dlltest程序所在目录
3,project\setting , 选择 link选项卡, 在object/library modules 中 输入 dll1.lib
4,现在可以执行程序。
如果要查看可执行程序的输入信息,以及加载的dll信息,在dlltest.exe目录下输入 dumpbin -imports dlltest.exe
19.3.2 depends工具
19.4 完善Win32DLL例子
为DLL工程添加一个头文件
在调用此头文件的项目里, #include "..\DLL11\DLL11.h
Note: 太奇怪的路径
19.5
从DLL中导出类
#include <windows.h>
#include <stdio.h>
Void Point::output(int x, int y)
{
//返回调用者进程当前正在使用的那个窗口的句柄
HWND hwnd = GetForegrounfWindow();
//获取DC
HDC hdc=GetDC(hwnd);
Char buf[20];
Memset(buf,0,20);
Sprintf(buf,""x=%d,y=%d",x,y);
TextOut(hdc,0,0,buf,strlen(buf));
//释放DC
ReleaseDC(hwnd,hdc);
}
可以不导出整个类
只对类中的某个函数放置宏,用于导出
19.6名字问题
1,函数加上限定符 extern "C"
2, 上述方法 在函数改变调用约定,如添加_stdcall 关键字。
标准调用约定就是WINAPI调用约定,也就是pascal 调用约定。 这时导出函数名字会发生改变
3,通过模块定义文件(DEF)解决上述问题
添加dll2.def 文件
LIBRARY DLL2 //指定动态链接库的内部名称
EXPORTS //表面dll将要导出的函数
Add
Subtract
19.7 显示加载方式加载dll
19.7.1 loadlibary 函数
客户程序只需要.dll 文件, 不需要函数声明的头文件和引入库文件
1,复制dll2.dll, 删除dll.lib 连接,
2,使用动态方式加载动态链接库时,用
Hmodule Loadlibary(lpctstr lpfilename); //将指定的可执行模块映射到调用进程的地址控件。
3,获取该动态链接库中导出函数的地址
Farproc GetProcAddredd( hmodule hModule, lpcstr lpProcName);
加载dll2.dll,并访问它提供的导出函数
1,定义hmodule 变量, loadlibrary
2,宏定义函数指针类型,再定义变量, getprocaddress
3,判断函数指针变量,有误则返回
4,调用函数
19.7.2 调用约定
当dll中导出函数采用标准调用约定时,访问该dll的客户端程序也应该采用该约定类型来访问相应的导出函数
19.7.3 根据序号访问dll 的导出函数
不用函数命, 而用函数序号 makeintresource(1);
19.8 DllMain函数
19.9 MFC DLL
MFC 扩展 DLL 与 MFC 常规DLL 区别是,前者可以导出MFC类,后者只能导出自己编写的c++类。
采用动态加载方式使用dll时,在需要访问时,调用 loadlibrary函数加载该dll。
当不再需要访问dll时,调用 freelibrary 释放对该dll 的引用。