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