一、动态链结库的动态加载简介
DLL创建与使用方法浅谈(1)中为通过引入库(.lib)文件和声明文件使用DLL的方法,本博文介绍的为动态加载DLL文件。无需引入库,也无需声明。动态的加载DLL库函数内容。
二、DLL创建和动态加载方法(运行时动态链接)
步骤1、DLL中函数创建
file1.cpp---------------------------------------------------
int Add(intx,int y)
{
return x+y;
}
int Subtract(intx,int y)
{
return x-y;
}
步骤2、导出内容声明文件创建
file2.def---------------------------------------------------
//以使得其他语言编制的程序也能使用我们的动态链接库。
LIBRARY Dll2 (可选项)
EXPORTS //导出关键字
Subtract //函数名1
Add //函数名2
//即使调用_stdcall约定,也不会发生改编,而只会调用这里显示的Add字符串
更名导出及和数字编号指定。导出 definitions 的语法为:
entryname[=internalname][@ordinal [NONAME]] [PRIVATE] [DATA]
步骤3、EXE动态引用关键代码
HINSTANCE hInst;
hInst=LoadLibrary("Dll2.dll"); //使用动态加载
typedef int (*ADDPROC)(int a,int b);
//如果在DLL的函数中调用_stdcall,相应的应该把代码改为
//typedef int(_stdcall *ADDPROC)(int a,int b); //注意到处函数的调用约定
ADDPROC Add=(ADDPROC)GetProcAddress(hInst,"Add");//构造一个函数指针
if(!Add)
{
MessageBox("获取函数地址失败!");
return;
}
CString str;
str.Format("3+5=%d",Add(3,5));
MessageBox(str);
因为调用LoadLibrary时动态加载动态链接库,所以不需要头文件和.lib文件
如果我们在动态链接库中使用标准调用约定_stdcall,而在可执行程序中使用动态加载DLL,会发生名字重编,如果知道DLL中函数的序号,这时可以使用宏MAKEINTRESOURCE把序号转变成名字,如:
ADDPROCAdd=(ADDPROC)GetProcAddress(hInst,MAKEINTRESOURCE(1));
三、与DLL有关重要函数的介绍
BOOL WINAPIDllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved);
需要WINDOWS系统传入参数时使用上面函数。
DllMain是DLL的入口与出口,进行初始化与退出处理。如果初始化成功应返回TRUE。
BOOLFreeLibrary( HMODULE hModule);
当我们的动态链接库不再使用时可以调用FreeLibrary使动态链接库使用计数减1,当使用计数为零时,系统会收回模块资源。
LoadLibrary(szDll):加载szDll,返回HANDLE。加载成功后可以用GetProcAddress(hLibrary,szFunction)获得函数地址,或用LoadBitmap等加载资源。
四、DLL共享内存功能简介
动态链接库分配的内存空间由应用程序所有,不同的应用程序调用相同的DLL数据不同。如果想要的数据内存在不同的应用程序或同一应用程序的不同实例之间共享,就要用到共享内存,实际上是一个内存映射(Memory-mapped)文件。在#prama data_seg("shared")与#pragma data_seg()之间定义的变量都可共享,但必须要初始化,否则编译器会把变量定义在未初始化数据区,而不是"shared"。“shared”是数据区名称,可以随意取。为共享数据,还要修改链接器命令,加上“/SECTION:shared,RWS”参数,或者在源文件中加入链接命令#prama comment(linker,"/SECTION:shared,RWS"),告诉链接器shared数据区有读写共享属性。
例:
#pragma data_seg("shared")
TCHAR buffer[30] = "HELLO WORLD!";
#pragma data_seg()
#pragma comment(linker, "/SECTION:shared,RWS")
// R read W write S Shared
五、DLL资源
在动态链接库中可以加载资源(图标、字符串、位图等)。如果从该库中加载,需要自己的实例句柄(DllMain的hInstance参数);如果从调用它的EXE文件中加载,则需要程序实例句柄。
在动态链接库中注册窗口类或创建窗口有些麻烦。这两个功能都要用实例句柄,如果使用动态库的句柄,窗口消息仍然通过调用它的程序窗口。所以如果必须要这样,最好使用调用它的实例句柄。由于模态对话栻在消息循环之外,DialogBox可以用动态库的实例句柄。