Windows API 集
重要
本主题中的信息适用于所有版本的 Windows 10 及更高版本。 我们在这里将这些版本称为“Windows”,并在必要时指出任何例外情况。
所有版本的 Windows 都共享称为核心 OS 的操作系统 (OS) 组件(在某些上下文中,此通用基础也称为 OneCore)。 在核心 OS 组件中,Win32 API 组织为称为 API 集的功能组。
API 集的目的是提供与实现给定 Win32 API 的主机 DLL 和 API 所属的功能契约的体系结构分离。 API 集在实现和协定之间提供的分离为开发人员提供了许多工程优势。 具体而言,在代码中使用 API 集可以提高与 Windows 设备的兼容性。
API 集专门针对以下方案:
尽管电脑支持 Win32 API 的完整广度,但其他 Windows 设备(如 HoloLens、Xbox 和其他设备)上只能使用 Win32 API 的一个子集。 API 集名称提供一种查询机制,可以清楚地检测某个 API 在任何给定设备上是否可用。
某些 Win32 API 实现存在于不同 Windows 设备上具有不同名称的 DLL 中。 在检测 API 可用性和延迟加载 API 时,使用 API 集名称而不是 DLL 名称,无论 API 实际实现在哪里,都可以为实现提供正确的路径。
有关详细信息,请参阅 API 集加载程序操作和检测 API 集可用性。
API 集和 dll 是一回事吗?
不是 - API 集名称是物理 .dll
文件的虚拟别名。 这是一种实现隐藏技术,作为调用者,你不必确切地知道哪个模块托管信息。
该技术允许在不同 Windows 版本和版次上重构模块(拆分、合并、重命名等)。 应用程序仍然链接,并且在运行时仍然被路由到正确的代码。
那么,为什么 API 集的名称中具有 .dll
? 原因在于 DLL 加载程序的实现方式。 加载程序是操作系统的一部分,用于加载 DLL 和/或解析对 DLL 的引用。 在前端,加载程序要求传递给 LoadLibrary 的任何字符串都以“.dll”终止。 但在前端之后,加载程序可以去掉后缀,并使用结果字符串查询 API 集数据库。
LoadLibrary(和延迟加载)成功地使用 API 集名称(其中带有“.dll”);但在电脑上的任何地方不一定有该名称的实际文件。
链接伞型库
为了更轻松地将代码限制为核心 OS 中支持的 Win32 API,我们提供了一系列伞型库。 例如,名为 OneCore.lib
的伞型库为所有 Windows 设备通用的 Win32 API 子集提供导出。
有关更多详细信息,请参阅 Windows 伞型库。
API 集协定名称
API 集合由一个强协定名称标识,该名称遵循库加载程序识别的这些标准约定。
- 名称必须以字符串 api- 或 ext- 开头。
- 以 api- 开头的名称表示所有 Windows 版本上存在的满足 API 版本要求的 API。
- 以 ext- 开头的名称表示并非所有 Windows 版本都存在的 API。
- 名称必须以序列 l<n>-<n>-<n> 结尾,其中 n 由十进制数字组成。
- 名称的正文可以是字母数字字符,也可以是短划线 (-)。
- 此名称不区分大小写。
以下是 API 集协定名称的一些示例:
- api-ms-win-core-ums-l1-1-0
- ext-ms-win-com-ole32-l1-1-5
- ext-ms-win-ntuser-window-l1-1-0
- ext-ms-win-ntuser-window-l1-1-1
可以在加载程序操作的上下文中使用 API 集名称,如 LoadLibrary 或 P/Invoke,而不是 DLL 模块名称,以确保无论 API 在当前设备上实际实现的位置如何,都可以正确地路由到实现。 但是,执行此操作时,必须将字符串 .dll 附加在约定名称的末尾。 这是加载程序正常运行的要求,实际上不被视为协定名称的一部分。 尽管在这种情况下,协定名称看起来与 DLL 名称相似,但它们与 DLL 模块名称有根本不同,并且不会直接引用磁盘上的文件。
除了在加载程序操作中追加字符串 .dll 外,API 集协定名称应被视为与特定协定版本相对应的不可变标识符。
标识 Win32 API 的 API 集
若要确定特定 Win32 API 是否属于 API 集,请查看 API 参考文档中的要求表。 如果 API 属于 API 集,则文章中的要求表列出了 API 集名称和首次引入 API 集的 Windows 版本。 有关属于 API 集的 API 的示例,请参阅以下文章: