Run-Time 动态链接

当应用程序调用 LoadLibraryLoadLibraryEx 函数时,系统会尝试查找 DLL(有关详细信息,请参阅 Dynamic-Link 库搜索顺序)。 如果搜索成功,系统将 DLL 模块映射到进程的虚拟地址空间,并递增引用计数。 如果调用 LoadLibraryLoadLibraryEx 指定一个 DLL,该 DLL 的代码已映射到调用进程的虚拟地址空间中,该函数只会返回 DLL 的句柄并递增 DLL 引用计数。 请注意,两个 DLL 具有相同的基本文件名和扩展名,但在不同的目录中被发现,不被视为同一 DLL。

系统在调用 LoadLibraryLoadLibraryEx的线程上下文中调用入口点函数。 如果进程已通过调用 LoadLibraryLoadLibraryEx,且对 FreeLibrary 函数没有相应的调用,则不会调用入口点函数。

如果系统找不到 DLL 或入口点函数返回 FALSE,LoadLibraryLoadLibraryEx 返回 NULL。 如果 LoadLibraryLoadLibraryEx 成功,它将向 DLL 模块返回句柄。 此过程可以使用此句柄在调用 GetProcAddressFreeLibraryFreeLibraryAndExitThread 函数中标识 DLL。

GetModuleHandle 函数返回 GetProcAddressFreeLibraryFreeLibraryAndExitThread中使用的句柄。 仅当 DLL 模块已通过加载时链接或先前调用 LoadLibraryLoadLibraryEx映射到进程的地址空间时,getModuleHandle 函数才会成功。LoadLibraryLoadLibraryEx不同,GetModuleHandle 不会递增模块引用计数。 GetModuleFileName 函数检索与 GetModuleHandleLoadLibraryLoadLibraryEx返回的句柄关联的模块的完整路径。

此过程可以使用 GetProcAddress,通过 LoadLibrary 返回的 DLL 模块句柄或 LoadLibraryExGetModuleHandle获取 DLL 中导出的函数的地址。

不再需要 DLL 模块时,进程可以调用 FreeLibraryFreeLibraryAndExitThread。 如果引用计数为零,这些函数会减少模块引用计数,并从进程的虚拟地址空间取消映射 DLL 代码。

运行时动态链接使进程能够继续运行,即使 DLL 不可用也是如此。 然后,该过程可以使用备用方法来实现其目标。 例如,如果进程找不到一个 DLL,则可以尝试使用另一个 DLL,也可以通知用户出现错误。 如果用户可以提供缺失 DLL 的完整路径,则进程可以使用此信息加载 DLL,即使它不在普通搜索路径中也是如此。 这种情况与加载时链接形成鲜明对比,如果系统找不到 DLL,则系统只会终止进程。

如果 DLL 使用 DllMain 函数对进程的每个线程执行初始化,则运行时动态链接可能会导致问题,因为调用 LoadLibraryLoadLibraryEx 之前存在的线程不会调用入口点。 有关如何处理此问题的示例,请参阅 在 Dynamic-Link 库中使用线程本地存储。

使用运行时动态链接