Run-Time动态链接
当应用程序调用 LoadLibrary 或 LoadLibraryEx 函数时,系统会尝试查找 DLL (以了解详细信息,请参阅 动态链接库搜索顺序) 。 如果搜索成功,系统会将 DLL 模块映射到进程的虚拟地址空间,并递增引用计数。 如果对 LoadLibrary 或 LoadLibraryEx 的调用指定了一个 DLL,该 DLL 的代码已映射到调用进程的虚拟地址空间中,则函数仅返回 DLL 的句柄并递增 DLL 引用计数。 请注意,具有相同基本文件名和扩展名但位于不同目录中的两个 DLL 不被视为同一 DLL。
系统在调用 LoadLibrary 或 LoadLibraryEx 的线程上下文中调用入口点函数。 如果进程已通过对 LoadLibrary 或 LoadLibraryEx 的调用加载了 DLL,但没有对 FreeLibrary 函数的相应调用,则不会调用入口点函数。
如果系统找不到 DLL 或入口点函数返回 FALSE, 则 LoadLibrary 或 LoadLibraryEx 返回 NULL。 如果 LoadLibrary 或 LoadLibraryEx 成功,它将返回 DLL 模块的句柄。 进程可以使用此句柄在调用 GetProcAddress、 FreeLibrary 或 FreeLibraryAndExitThread 函数时标识 DLL。
GetModuleHandle 函数返回 GetProcAddress、FreeLibrary 或 FreeLibraryAndExitThread 中使用的句柄。 仅当 DLL 模块已通过加载时链接或先前调用 LoadLibrary 或 LoadLibraryEx 映射到进程的地址空间时,GetModuleHandle 函数才会成功。 与 LoadLibrary 或 LoadLibraryEx 不同, GetModuleHandle 不会递增模块引用计数。 GetModuleFileName 函数检索与 GetModuleHandle、LoadLibrary 或 LoadLibraryEx 返回的句柄关联的模块的完整路径。
进程可以使用 GetProcAddress 通过 LoadLibrary 或 LoadLibraryExGetModuleHandle 返回的 DLL 模块句柄获取 DLL 中导出函数的地址。
当不再需要 DLL 模块时,进程可以调用 FreeLibrary 或 FreeLibraryAndExitThread。 如果引用计数为零,这些函数会递减模块引用计数,并从进程的虚拟地址空间取消映射 DLL 代码。
运行时动态链接使进程能够继续运行,即使 DLL 不可用也是如此。 然后,该过程可以使用替代方法来实现其目标。 例如,如果一个进程找不到一个 DLL,它可以尝试使用另一个 DLL,或者它可能会通知用户出错。 如果用户可以提供缺少的 DLL 的完整路径,则进程可以使用此信息加载 DLL,即使它不在正常的搜索路径中。 这种情况与加载时链接形成鲜明对比,在该链接中,如果系统找不到 DLL,系统只会终止进程。
如果 DLL 使用 DllMain 函数对进程的每个线程执行初始化,则运行时动态链接可能会导致问题,因为不会对调用 LoadLibrary 或 LoadLibraryEx 之前存在的线程调用入口点。 有关如何处理此问题的示例,请参阅 在Dynamic-Link库中使用线程本地存储。
相关主题