根据我的测试,有两种选择:
我正在开发/测试一些 Windows 10 21H2,它提供了一个实现PathCchCanonicalizeEx
已经在某些 DLL 中了。因此,如果源 DLL 已知,则可以使用IMPLIB
or MKEXP
手动创建导入库。我这样做了,然后添加了创建的库IMPLIB
对于我的项目,链接器错误立即消失了。
不过,要知道在哪里并不容易PathCchCanonicalizeEx
被放置在 https://stackoverflow.com/questions/57354840/which-dll-has-pathcchappend。人们很容易找到api-ms-win-core-path-l1-1-0.dll
,但那个东西不是磁盘上的实际文件,因此不能被使用IMPLIB
or MKEXP
。该名称只是库加载器的虚拟概念,用于处理现代 Windows 的相同命名的 API 集,即扩展.dll
并不意味着它根本就是一个文件。
您可以在加载器操作(例如 LoadLibrary 或 P/Invoke)的上下文中使用 API 集名称,而不是 DLL 模块名称,以确保实现正确的路由,无论 API 在当前设备上的何处实际实现。但是,执行此操作时,必须在合约名称末尾附加字符串 .dll。这是加载程序正常运行的要求,实际上并不被视为合约名称的一部分。尽管合约名称在这种情况下看起来与 DLL 名称类似,但它们与 DLL 模块名称有本质上的不同,并且不直接引用磁盘上的文件。
https://learn.microsoft.com/en-us/windows/win32/apiindex/windows-apisets#api-set-contract-names https://learn.microsoft.com/en-us/windows/win32/apiindex/windows-apisets#api-set-contract-names
你真正需要做的是KernelBase.dll
,这是偶数由 MS 记录 https://github.com/MicrosoftDocs/sdk-api/blob/docs/sdk-api-src/content/pathcch/nf-pathcch-pathcchappend.md.
implib "KernelBase x86.lib" C:\Windows\SysWOW64\KernelBase.dll
implib "KernelBase x86-64.lib" C:\Windows\System32\KernelBase.dll
- 模块定义文件 https://docwiki.embarcadero.com/RADStudio/Sydney/en/Module_Definition_Files
手动创建 LIB 文件的缺点是需要在项目中维护这些文件。事情取决于目标是 32 位还是 64 位、调试还是发布,因此路径可能会变得有点复杂,可能需要使用目标的占位符和类似的东西在项目设置中为库创建相对路径。
看来这一切都可以避免模块定义文件 https://blogs.embarcadero.com/how-to-build-and-use-a-simple-dll/,其目的是提供 IMPORT 和 EXPORT 语句,以使用其他 DLL 导出的函数或使其他 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集名称的原因,文件的格式根本就是错误的。