键盘快捷键

在章节间导航

S/ 在书中搜索

? 显示此帮助

Esc 隐藏此帮助

理解 windows-targets crate

windowswindows-sys crate 依赖于 windows-targets crate 以获得链接器支持。windows-targets crate 包含导入库,支持语义版本控制,并可选地支持 raw-dylib。它为以下目标提供了显式导入库:

  • i686_msvc
  • x86_64_msvc
  • aarch64_msvc
  • i686_gnu
  • x86_64_gnu
  • x86_64_gnullvm
  • aarch64_gnullvm

导入库包含链接器用于解析由 DLL 导出的函数的外部引用的信息。这允许操作系统在加载时识别特定的 DLL 和函数导出。导入库是工具链和架构特定的。换句话说,根据您是使用 MSVC 还是 GNU 工具链编译,以及您是为 x86 还是 ARM64 架构编译,需要不同的 lib 文件。请注意,导入库不包含任何代码,静态库则包含。

虽然 GNU 和 MSVC 工具链通常提供一些导入库来支持 C++ 开发,但这些 lib 文件通常不完整、缺失或完全错误。这可能导致非常难以诊断的链接器错误。windows-targets crate 确保 windowswindows-sys crate 定义的所有函数都可以链接,而无需依赖工具链分发的隐式 lib 文件。这确保了依赖项可以通过 Cargo 进行管理,并简化了交叉编译。windows-targets crate 还包含版本特定的 lib 文件名,以确保语义版本兼容性。如果没有此功能,链接器将简单地选择第一个匹配的 lib 文件名,并无法解析任何缺失或不匹配的导入。

注意:通常,您根本不需要考虑 windows-targets crate。windowswindows-sys crate 会自动依赖 windows-targets crate。只有在极少数情况下,您才需要直接使用它。

首先将以下内容添加到您的 Cargo.toml 文件中

[dependencies.windows-targets]
version = "0.52"

使用 link 宏定义您希望调用的外部函数

#![allow(unused)]
fn main() {
windows_targets::link!("kernel32.dll" "system" fn SetLastError(code: u32));
windows_targets::link!("kernel32.dll" "system" fn GetLastError() -> u32);
}

根据需要使用任何 Windows API

fn main() {
    unsafe {
        SetLastError(1234);
        assert_eq!(GetLastError(), 1234);
    }
}

默认情况下,link 宏将导致链接器使用捆绑的导入库。使用 windows_raw_dylib Rust 构建标志编译将导致 Cargo 完全跳过下载导入库,而是使用 raw-dylib 自动解析导入。然后 Rust 编译器将直接创建导入条目。这无需更改任何代码即可工作。如果没有 windows-targets crate,在链接器和 raw-dylib 导入之间切换需要非常复杂的代码更改。截至本文撰写之时,raw-dylib 功能尚未稳定。