0

我有一个使用旧版 32 位 C++ 编译器的旧版 Windows 项目。由于各种原因,我需要使用 Windows 8+ 功能PathCchCanonicalizeEx。C++Builder 似乎为此提供了头文件和一些模块定义文件,但我找不到任何要链接的库:

[ilink32 Error] Error: Unresolved external 'PathCchCanonicalizeEx' referenced from C:\[...]\WIN32\DEBUG\TMP\FILE.OBJ

我该如何解决这个问题?我需要添加Windows 8.1 SDK吗?必要的库是否只是以不同的方式命名而我找不到?完全不同的东西?

4

1 回答 1

0

根据我的测试,有两种选择:

  1. 暗示/MKEXP

我正在开发/测试一些 Windows 10 21H2,它PathCchCanonicalizeEx已经在一些 DLL 中提供了一个实现。因此,如果该源 DLL 已知,则可以使用IMPLIBMKEXP手动创建导入库。我这样做了,在将创建的库添加IMPLIB到我的项目后,链接器错误立即消失了。

PathCchCanonicalizeEx 不过,要知道放在哪里并不容易。很容易找到api-ms-win-core-path-l1-1-0.dll,但那个东西不是磁盘上的实际文件,因此不能被IMPLIBor使用MKEXP。该名称只是库加载器的一个虚拟概念,用于处理现代 Windows 的同名 API 集,扩展名.dll并不意味着它是一个文件。

您可以在加载程序操作的上下文中使用 API 集名称,例如 LoadLibrary 或 P/Invoke,而不是 DLL 模块名称,以确保无论 API 实际在当前设备上的何处实现,都可以正确路由到实现。但是,当您这样做时,您必须在合同名称的末尾附加字符串 .dll。这是加载程序正常运行的要求,实际上不被视为合约名称的一部分。尽管在这种情况下合同名称看起来与 DLL 名称相似,但它们与 DLL 模块名称根本不同,并且不直接引用磁盘上的文件。

https://docs.microsoft.com/en-us/windows/win32/apiindex/windows-apisets#api-set-contract-names

您真正需要使用的是KernelBase.dll,甚至由 MS 记录

implib "KernelBase x86.lib"    C:\Windows\SysWOW64\KernelBase.dll
implib "KernelBase x86-64.lib" C:\Windows\System32\KernelBase.dll
  1. 模块定义文件

手动创建 LIB 文件的缺点是需要与项目一起维护这些文件。事情取决于目标是 32 位还是 64 位、DEBUG 或 RELEASE,因此路径可能会变得有点复杂,可能需要使用目标的占位符等为项目设置中的库创建相对路径。

似乎所有这些都可以通过Module Definition Files来避免,其目的是提供 IMPORT 和 EXPORT 语句以使用其他 DLL 导出的函数,或者使其他拥有自己的函数的函数成为可能。.def我通过简单地使用扩展名和我的其他项目文件创建一个名为我的应用程序的文件,成功地解决了我的链接器问题。不过,该文件需要添加到项目中。

dbxml.cbproj
dbxml.cbproj.local
dbxml.cpp
dbxml.def
dbxml.res
[...]

以下内容使应用程序使用正确 DLL 中的正确函数。但是,没有工作的是使用 API 集名称,这导致链接器出现错误消息。

IMPORTS
    KernelBase.PathCchCanonicalizeEx
IMPORTS
    api-ms-win-core-path-l1-1-0.PathCchCanonicalizeEx

[ilink32 错误] “ilink32”的命令行开关无效。参数“ItemSpec”不能为空。

[ilink32 错误] 致命:处理 .DEF 文件时出错

后者是在重新启动 C++Builder 之后,所以我猜测文件的格式是错误的,因为 API 集名称。

于 2022-02-25T14:54:14.487 回答