4

我一直在使用动态库和 GetProcAddress 的东西很长一段时间,但它总是看起来乏味、智能敌对和丑陋的做事方式。

有谁知道在与旧操作系统兼容的同时导入新功能的干净方法。

假设我想使用一个 XML 库,它是 Vista 的一部分。我调用 LoadLibraryW,然后如果 HANDLE 不为空,我可以使用这些函数。

但我真的不想走#typedef (void*)(PFNFOOOBAR)(int, int, int)and PFNFOOOBAR foo = reinterpret_cast<PFNFOOOBAR>(GetProcAddress(GetModuleHandle(), "somecoolfunction"));,一直到 50 次。

是否有一个非黑客解决方案可以避免这种混乱?

我正在考虑在项目设置中添加coolxml.lib,然后在delayload dll 列表中包含coolxml.dll,并且,也许,复制我将在所需文件中使用的几个函数签名。然后检查 LoadLibraryW 返回的非空值,如果它是非空值,则像在常规程序流中一样分支到 Vista 分支。

但我不确定 LoadLibrary 和 delay-load 是否可以一起工作,以及某些分支预测是否在某些情况下不会搞砸。

另外,不确定这种方法是否可行,以及升级到下一个 SDK 后是否会导致问题。

4

3 回答 3

4

IMO、LoadLibrary 和 GetProcAddress 是最好的方法。

(制作一些包装器对象来为您处理这些问题,这样您就不会因为这种逻辑和丑陋而污染您的主代码。)

  1. DelayLoad 带来了安全问题(请参阅此 OldNewThing 帖子)(编辑:但如果您确保从未在旧版本的 Windows 上调用这些 API,则不会)。

    DelayLoad 还很容易意外地依赖并非在所有目标上都可用的 API。是的,您可以使用工具检查您在运行时调用的 API,但最好在编译时处理这些事情,IMO,这些工具只能检查您在它们下运行时实际执行的代码。

  2. 此外,请避免使用不同的 Windows 标头版本编译代码的某些部分,除非您非常小心地隔离代码和传递给/从它传递的对象。

    这并不是绝对错误的——对于插件 DLL 之类的事情,这完全正常,两个完全不同的团队可能在不知道彼此针对的 SDK 版本的情况下在这两个模块上工作——但如果你不知道,它可能会导致棘手的问题小心,所以一般最好避免。

    如果您混合标头版本,您可能会遇到非常奇怪的错误。例如,我们有一个静态对象,其中包含一个 OS 结构,它在 Vista 中改变了大小。我们的大部分项目都是为 XP 编译的,但是我们添加了一个新的 .cpp 文件,该文件的名称恰好以 A 开头,并且设置为使用 Vista 头文件。然后(任意)该新文件成为触发静态对象分配的文件,使用 Vista 结构大小,但该对象的实际代码是使用 XP 结构构建的。构造函数认为对象的成员与分配对象的代码位于不同的位置。奇怪的事情发生了!

    一旦我们了解了这一点,我们就完全禁止了这种做法。我们项目中的所有内容都使用 XP 头文件,如果我们需要新头文件中的任何内容,我们手动将其复制出来,并在需要时重命名结构。

编写所有 typedef 和 GetProcAddress 的东西,从头文件中复制结构和定义是非常乏味的(这似乎是错误的,但它们是二进制接口,所以不会改变)(不要忘记检查#pragma也打包东西:(),但如果你想要最好的编译时问题通知,IMO 是最好的方法。

我相信其他人会不同意!

PS:在某个地方,我制作了一个小模板,以使 GetProcAddress 的东西稍微不那么乏味......试图找到它;当/如果我这样做时会更新这个。找到了,但实际上并没有那么有用。事实上,我的代码甚至都没有使用它。:)

于 2010-12-10T10:40:51.110 回答
2

是的,使用延迟加载。这将丑陋留给编译器。当然,您仍然必须确保您没有在 XP 上调用 Vista 函数。

于 2010-12-10T09:46:30.020 回答
1

延迟加载是避免直接使用LoadLibrary()and的最佳方式GetProcAddress()。关于提到的安全问题,您唯一能做的就是使用延迟加载挂钩来确保(并可选择强制)在dliNotePreLoadLibrary通知期间使用正确的系统路径加载所需的 DLL,而不是相对于您的应用程序文件夹。当所需的 API 函数不可用时,使用回调还允许您在dliFailLoadLib/通知中替换您自己的后备实现。dliFailGetProc这样,您的其余代码就不必担心平台差异(或很少)。

于 2011-04-02T05:47:23.047 回答