我已经使用了动态库和getProcaddress的东西了一段时间,但是似乎总是乏味,智力敌意和做事的丑陋方式。

有谁知道一种干净的方式来导入新功能,同时与较旧的OS保持兼容。

假设我想使用XML库,该库是Vista的一部分。我调用LoadLibraryW,然后如果句柄不为NULL,则可以使用该功能。

但是我真的不想去 #typedef (void*)(PFNFOOOBAR)(int, int, int)PFNFOOOBAR foo = reinterpret_cast<PFNFOOOBAR>(GetProcAddress(GetModuleHandle(), "somecoolfunction"));, ,所有这些时间50。

我可以避免这种混乱的解决方案吗?

我当时考虑在项目设置中添加coolxml.lib,然后在delayload dll列表中包括coolxml.dll,也许复制我将在所需文件中使用的少数功能签名。然后,使用非null检查LoadLibraryw返回,如果是非零件,则像常规程序流中的分支一样分支到Vista分支。

但是我不确定LoadLibrary和delay-Load是否可以一起工作,并且某些分支预测在某些情况下不会弄乱问题。

另外,不确定这种方法是否会起作用,并且在升级到下一个SDK后是否会引起问题。

有帮助吗?

解决方案

延迟加载是避免使用的最佳方法 LoadLibrary()GetProcAddress() 直接地。关于提到的安全问题,关于您唯一可以做的就是使用 延迟负载钩 为了确保(并有权)在此期间加载所需的DLL dliNotePreLoadLibrary 使用正确的系统路径通知,而不是相对于您的应用程序文件夹。使用回调还可以允许您在 dliFailLoadLib/dliFailGetProc 当所需的API函数不可用时的通知。这样,您的其余代码不必担心平台差异(或很少)。

其他提示

IMO,LOADLIBRARY和GETPOROCADDRESS是最好的方法。

(制作一些为您处理的包装对象,因此您不会用这种逻辑和丑陋来污染您的主要代码。)

  1. 延迟负载带来了安全问题(查看这个旧的帖子)(编辑:虽然不要确保您从未在Windows的较旧版本上调用这些API)。

    延迟载荷还使意外依赖API变得太容易,而API将无法在所有目标上使用。是的,您可以使用工具检查您在运行时调用哪些API,但是最好在编译时间,IMO处理这些内容,而这些工具只能检查您在其下运行时实际锻炼的代码。

  2. 另外,避免将代码的某些部分与不同的Windows标头版本一起编译,除非您非常小心地隔离代码和传递给它的对象。

    这不是绝对错误的 - 与插件DLL这样的事情完全正常小心,因此最好避免使用它。

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

    一旦到达底部,我们就完全禁止了这种做法。我们项目中的所有内容都使用XP标头,如果我们需要从较新的标题中进行任何内容,我们将其手动复制它,并在需要时重命名结构。

编写所有Typedef和getProcaddress的内容,复制结构并从标题中定义的内容非常繁琐(这似乎是错误的,但它们是二进制界面,所以不会更改)也可以打包东西:(),但是如果您想要最佳的编译时间通知,这是IMO。

我敢肯定其他人会不同意!

PS:在某个地方,我制作了一些模板,以使GetProcaddress的内容稍微乏味……试图找到它; /如果我这样做时会更新此信息。 找到了它,但实际上并不是那么有用。实际上,我的代码甚至都没有使用。 :)

是的,使用延迟加载。这使编译器的丑陋使人丑陋。当然,您仍然必须确保您不会在XP上调用Vista功能。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top