我正在编译由几个.o
文件组成的自己的DLL。其中一个.o
文件具有仅调用Windows 7支持的SHLoadLibraryFromItem
的函数。除非使用DLL的应用程序在Windows 7上运行,否则永远不会调用该函数。(是的,我确定。)
但是,在较旧版本的Windows(例如XP)上运行应用程序时,整个应用程序在启动时崩溃,并显示“无法找到指定的过程”。虽然错误没有指定找不到哪个程序,但如果我将对SHLoadLibraryFromItem
的调用注释掉,那么一切正常。
问题:
SHLoadLibraryFromItem
,即使它没有在XP上调用?SHLoadLibraryFromItem
,即某种懒惰的绑定?我能想到的唯一方法就是:
LoadLibrary
加载SHLoadLibraryFromItem
所在的Windows DLL并使用GetProcAddress
手动获取地址到指向函数的指针并使用指针调用{{1}而不是?还有其他想法吗?我真的更喜欢上面提到的某种懒惰绑定。
请仔细阅读我实际上的事情。我在第一段中明确指出SHLoadLibraryFromItem
不被调用,除非我知道应用程序实际上是在WINDOWS 7上运行。
仅在DLL 加载时才会崩溃。
答案 0 :(得分:10)
链接器将模块中的引用嵌入到所使用的每个API函数中。当Windows加载程序加载可执行文件及其模块时,它需要将代码中的所有调用“挂钩”到实际加载API函数的内存中的位置。如果找不到它们,它就不会继续。
使用LoadLibrary
和GetProcAddress
是解决此问题的“标准”方法。
使用两个DLL对您没有帮助,因为只要其中一个无法加载您的应用程序仍然无法启动。您可以通过使用延迟加载来解决这个问题,将所有依赖于新O / S的代码放在一个单独的模块中,并将所有对该模块的调用包装在Win32 SEH异常处理程序中(延迟加载时会出现SEH异常)无法加载模块)。优点是你可以使用“自动”链接而不需要乱七八糟的函数指针,但异常处理可能非常讨厌。
This article解释了一下,并提供了一些如何整齐地包装它的例子。
答案 1 :(得分:2)
为什么Windows试图找到 SHLoadLibraryFromItem即使它是 没有在XP上调用?
Windows在应用程序加载到内存时解析引用,而不是在进行调用时。这称为“动态链接”(与链接器的静态链接相反),但它不是真正动态的。因此,它不知道在运行时是否会调用特定方法。