上一主题介绍了 Rust for Windows 与 windows crate。
现在,让我们通过编写一个简单的控制台应用来试用 Rust for Windows,该应用从简单信息聚合(RSS)源下载博客文章的标题。
在要保存 Rust 项目的文件夹中启动命令提示符 (
cmd.exe) 和cd。使用 Cargo 新建一个名为“rss_reader”的 Rust 项目,并使用
cd转到新创建的文件夹中:> cargo new rss_reader > Created binary (application) `rss_reader` package > cd rss_reader然后在 VS Code 中打开 rss_reader 项目。
code .让我们实现主项目 rss_reader。 首先,在
Cargo.toml项目的根目录中打开该文件。 文件Cargo.toml是描述 Rust 项目的文本文件,包括它拥有的任何依赖项。在 windows crate 上添加依赖项,如下面的列表所示。 Windows crate 很大。 为了保持构建时间较短,我们将仅选择此代码所需的
Foundation_Collections和Web_Syndication特性。# Cargo.toml ... [dependencies.windows] version = "0.62.0" features = [ "Foundation_Collections", "Web_Syndication", ]注释
windowscrate 发布频繁。 检查 crates.io/crates/windows 是否有最新版本并相应地更新。然后,打开 rss_reader 项目的
src/main.rs源代码文件。 你将在那里找到 Cargo 默认的“Hello, world!” 代码。 将以下 use 语句添加到main.rs的开头:// src\main.rs use windows::{ core::*, Foundation::Uri, Web::Syndication::SyndicationClient }; fn main() { println!("Hello, world!"); }use 声明缩短了我们将要使用的类型的路径。 其有我们前面提到过的 Uri 类型。
要创建新的 Uri,请使用以下内容替代 Cargo 的默认 main 函数:
// src\main.rs ... fn main() -> Result<()> { let uri = Uri::CreateUri(h!("https://blogs.windows.com/feed"))?; Ok(()) }请注意,main 函数的返回类型是来自 windows::core:: 的 Result。 这会让事情变得更简单,因为我们常常需要处理操作系统(OS)API中的错误。 windows::core::Result 有助于我们进行错误传播和简洁的错误处理。
可以在代码行末尾看到问号运算符。 简而言之,我们这样做是为了利用 Rust 的错误传播和短路逻辑。 这意味着,对于这个简单的示例,我们不必执行一堆手动错误处理。 若要详细了解 Rust 的这项功能,请参阅利用 ? 运算符简化错误处理。
另请注意 windows crate 中的 h! 宏。 可使用它基于 Rust 字符串文本构造 HSTRING 引用。 WinRT API 广泛对字符串值使用 HSTRING。
为了下载此 RSS 源,我们将创建一个新的 SyndicationClient。
// src\main.rs ... fn main() -> windows::core::Result<()> { let uri = Uri::CreateUri(h!("https://blogs.windows.com/feed"))?; let client = SyndicationClient::new()?; Ok(()) }新函数是 Rust 构造函数。 windows crate 中的所有对象都遵循 Rust 约定,并将其构造函数命名为 new。
现在,我们可以使用 SyndicationClient 来检索源。
// src\main.rs ... fn main() -> windows::core::Result<()> { let uri = Uri::CreateUri(h!("https://blogs.windows.com/feed"))?; let client = SyndicationClient::new()?; let feed = client.RetrieveFeedAsync(&uri)?.get()?; Ok(()) }由于 RetrieveFeedAsync 是一个异步 API,因此我们使用阻止 get 函数来保持示例简单。 或者,可以使用
await函数中的async运算符协作等待结果。 具有图形用户界面的更复杂的应用将经常使用async。现在,我们可以循环访问结果项,然后只打印标题。 你还将在下面看到几行额外的代码来设置用户代理标头,因为某些 RSS 源需要这样做。
// src\main.rs ... fn main() -> windows::core::Result<()> { let uri = Uri::CreateUri(h!("https://blogs.windows.com/feed"))?; let client = SyndicationClient::new()?; client.SetRequestHeader( h!("User-Agent"), h!("Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)"), )?; let feed = client.RetrieveFeedAsync(&uri)?.get()?; for item in feed.Items()? { println!("{}", item.Title()?.Text()?); } Ok(()) }现在让我们通过单击运行>不带调试运行(或按下 Ctrl+F5)来确认可以生成并运行。 如果看到任何意外消息,请确保已成功完成 Hello, world! 教程(Rust 与 VS Code)。
文本编辑器中也嵌入了“调试”和“运行”命令。 或者,在
rss_reader文件夹的命令提示符中键入cargo run,这将构建并运行程序。
在下面的 VS Code“终端”窗格中,可以看到 Cargo 成功地下载并编译了 windows crate,缓存结果,并使用它们在更短时间内完成后续的生成操作。 然后,它会生成示例并运行该示例,并显示博客文章标题的列表。
这与为 Windows 编程 Rust 一样简单。 但实际上,很多开发人员都喜欢生成这个工具,这样 Rust 既可以解析基于 ECMA-335(公共语言基础结构 (CLI))的 .winmd 文件,也可以在运行时如实地使用基于 COM 的应用程序二进制接口 (ABI),同时兼顾安全性和效率。
显示消息框
我们确实说,Rust for Windows 允许你调用任何 Windows API(过去、现在和将来)。 因此,在本部分中,我们将显示几个 Windows 消息框。
就像我们对 RSS 项目执行的操作一样,应在包含 Rust 项目的文件夹的命令提示符
cd下进行。创建名为 message_box的新项目,并在 VS Code 中打开它:
> cargo new message_box > Created binary (application) `message_box` package > cd message_box > code .在 VS Code 中打开
Cargo.toml,然后为该项目添加 Windows 依赖项。# message_box\Cargo.toml ... [dependencies.windows] version = "0.62.0" features = [ "Win32_Foundation", "Win32_UI_WindowsAndMessaging", ]现在打开项目
src/main.rs的文件,并使用新命名空间添加use声明(如下所示)。 最后添加代码以调用 MessageBoxA 和 MessageBoxW 函数。 Windows API 文档主要是用 C/C++ 编写的,因此将 API 文档与 windows crate 中的 Rust 投影文档进行比较很有用:MessageBoxA (Rust) 和 MessageBoxW (Rust)。// src\main.rs use windows::{ core::*, Win32::UI::WindowsAndMessaging::* }; fn main() { unsafe { MessageBoxA(None, s!("Ansi"), s!("World"), MB_OK); MessageBoxW(None, w!("Wide"), w!("World"), MB_OK); } }如你所见,我们必须在
unsafe块中使用这些 Win32 应用程序接口(Win32 API)(请参阅 不安全块)。 另请注意 s! 和 w! 宏,它们用于从 Rust UTF-8 字符串字面量创建 LPCSTR 和 LPCWSTR 参数;就像我们使用 h! 宏为 rss_reader创建 HSTRING 一样。 Rust 本地支持 Unicode 和 UTF-8 字符串,因此优先使用带有 W 后缀的宽 Unicode Windows API,而不是带有 A 后缀的 ANSI API。 如果在代码中使用非英语文本,这一点非常重要。
生成和运行时,Rust 会显示两个 Windows 消息框。