延迟加载DLLs

10

我急需帮助,需要在Visual Studio中管理应用程序依赖项。该应用程序链接到一个仅适用于特定版本的Windows(比如Windows 7)的DLL文件,在其他环境中该DLL文件不应该被加载。作为一个完全陌生的话题,我要如何使用DLL延迟加载来实现这一点,因为网络上没有关于这个特定问题的良好参考。

谢谢


1
你是在询问延迟加载的工作原理,还是如何应用它? - xtofl
3个回答

11
您的项目可以通过在链接器/输入/延迟加载DLL字段中指定一个依赖项dll,以便在需要时才加载该dll。这个设置可以针对不同的构建配置进行不同的配置。

谢谢您的回复,但是如果适用的话,您能提供一个例子或者代码片段吗? :) - Zaid Amir
5
这就是延迟加载的关键所在:它是一种配置问题,而不是代码问题。 - xtofl
措辞似乎有误:当你说“你所依赖的DLL应该已经使用延迟加载功能进行了链接”时,你似乎是在指这个DLL从其组成的.obj文件中创建。/DELAY标志实际上是应用于执行_importing_的模块,而不是_imported_模块。这也是你可以延迟加载Windows 2000 DLL的原因,这些DLL可能没有构建此支持。 - MSalters
@MSalters:你是对的:第一个选项是为了支持dll的卸载。已更正,谢谢。 - xtofl

11

MSDN在这里提供了非常好的解释。

基本上,你需要将相关的DLL设置为延迟加载。这样,在调用该DLL中包含的函数之前,它不会被加载。

根据上面的链接,

Visual C++链接器现在支持延迟加载DLL。这使您无需使用Windows SDK函数LoadLibrary和GetProcAddress来实现DLL延迟加载。

在Visual C++ 6.0之前,运行时加载DLL的唯一方法是使用LoadLibrary和GetProcAddress;操作系统在加载使用它的可执行文件或DLL时加载DLL。

从Visual C++ 6.0开始,在静态链接DLL时,链接器提供了延迟加载DLL的选项,直到程序调用该DLL中的函数才加载。

应用程序可以使用帮助函数(由Visual C++提供默认实现)和/DELAYLOAD(延迟载入导入) 链接器选项来延迟加载DLL。帮助函数将通过调用LoadLibrary和GetProcAddress在运行时加载DLL。

如果:

程序可能不会调用DLL中的某个函数。

直到程序的执行较晚时才调用DLL中的函数。

您应该考虑延迟加载DLL。DLL的延迟加载可以在.EXE或.DLL项目的构建期间指定。延迟加载一个或多个DLL的.DLL项目不应该调用DllMain中的延迟加载入口点。


2

除了使用延迟加载,你是否考虑过使用 动态 加载LoadLibrary 以及 GetProcAddress?这可能更加简单易用。

typedef void (WINAPI *PGNSI)(LPSYSTEM_INFO);

// Call GetNativeSystemInfo if supported or GetSystemInfo otherwise.

PGNSI pGNSI;
SYSTEM_INFO si;

ZeroMemory(&si, sizeof(SYSTEM_INFO));

pGNSI = (PGNSI) GetProcAddress(
   GetModuleHandle(TEXT("kernel32.dll")), 
   "GetNativeSystemInfo");
if(NULL != pGNSI)
   pGNSI(&si);
else GetSystemInfo(&si);

13
如何编写可以被链接器自动生成的代码更加简单? - xtofl
2
如果你只想调用一个函数,那么这是可以的。但是,如果你想调用多个函数,我认为这是一个非常糟糕的选择。 - Goz
4
链接器中的延迟加载支持是专门旨在防止你必须处理LoadLibrary()和GetProcAddress()的! - Bids
4
在这个问题中,(我们假设)他知道该DLL将在Windows 7上可用,因此可以在调用延迟加载的DLL函数之前检测操作系统版本。但是,有时您无法确定系统上是否有可用的DLL以及可用的版本(因此可导出的函数),这种情况下,运行时动态链接是适当的尽管繁琐的解决方案。如果您没有某种方式以100%的确定性检测DLL和所需的导出函数的存在,则延迟加载可能会导致延迟崩溃。 - Zach Burlingame
我赞同xtofl和Bids的观点。使用运行时加载需要更多的工作。 - xiay

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接