原理
Win32系统内存中只有一份DLL,将其存放于Win32系统的全局堆栈中。当进程调用时,每个进程会收到DLL的一份映像。
使用
1.存在lib+dll+头文件:当编译器编译DLL文件后会生成3个文件,当全都拥有时可通过包含直接使用其函数
#pragma comment(lib,"libname.lib")
#include "libname.h"
func();
/*.
lib文件:存放库文件包含被DLL导出的函数名称和位置
.dll文件:存放DLL包含的函数与数据
exe文件使用lib文件链接到所需的dll文件,exe中不存放dll的代码而是存放其函数内存地址
*/
2.只有DLL文件:使用LoadLibrary加载映射DLL文件,然后通过GetProcAddress获取函数地址,然后调用函数。
typedef int (*FUNC)(void);
FUNC fnmyfunc=NULL;
//定义函数指针
HMODULE hMod = LoadLibrary("mydll.dll");
//最好写绝对路径以防止劫持
if(hMod)
{
fnmyfunc=(FUNC)GetProcAddress(hMod,"fnMyFunc");
//由于c++名称粉碎机制,会导致函数名称可能变为fnMyFunc_void或其他。可以将DLL中导出的函数声明为C函数extern "C"禁止名称粉碎。
if(fnmyfunc)
fnmyfunc();
FreeLibrary(hMod);
}
开发
dll文件入口为DllMain函数,原型为:
BOOL APIENTRY DllMain(HMODULE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
{
switch(ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
//进程、线程附加与卸载
break;
}
return TRUE;
};
当LoadLibrary被执行时该入口函数执行。
DLL中变量和函数要用MYDLL_API进行导出声明
MYDLL_API int nmydll=0;
MYDLL_API int fnmydll(vovid)
{return 42};
//MYDLL_API只要定义了MYDLL_EXPORTS宏则变为导出声明,否则为导入声明。宏在DLL工程的属性中定义。