RSS 阅读器教程(在 Windows 上使用 VS Code 的 Rust)

上一主题介绍了适用于 Windows 的 Rust ,以及 windows 包

现在,让我们通过编写一个简单的控制台应用来试用 Rust for Windows,该应用从简单信息聚合(RSS)源下载博客文章的标题。

  1. 启动命令提示符(cmd.exe),并 cd 到您要存放 Rust 项目的文件夹。

  2. 使用 Cargo,创建名为 rss_reader的新 Rust 项目,并将 cd 到新创建的文件夹:

    > cargo new rss_reader
    >     Created binary (application) `rss_reader` package
    > cd rss_reader
    
  3. 然后在 VS Code 中打开 rss_reader 项目。

    code .
    
  4. 让我们来实现 rss_reader 这个主要项目。 首先,在 Cargo.toml 项目的根目录中打开该文件。 文件 Cargo.toml 是描述 Rust 项目的文本文件,包括它拥有的任何依赖项。

    窗口 箱中添加依赖项,如以下列表所示。 窗口 箱很大。 为了保持构建时间较短,我们将仅选择此代码所需的 Foundation_CollectionsWeb_Syndication 特性。

    # Cargo.toml
    ...
    
    [dependencies.windows] 
    version = "0.43.0"
    features = [
        "Foundation_Collections",
        "Web_Syndication",
    ]
    
  5. 然后,打开 rss_reader 项目的 src/main.rs 源代码文件。 你将在那里找到 Cargo 默认的“Hello, world!” 代码。 将以下 使用 语句添加到 main.rs开头:

    // src\main.rs
    use windows::{
        core::*,
        Foundation::Uri,
        Web::Syndication::SyndicationClient
    };
    
    fn main() {
        println!("Hello, world!");
    }
    

    通过使用 声明,可以缩短我们将用到的类型路径。 有一个我们前面提到的 Uri 类型。

  6. 若要创建新的 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 包的 h! 宏。 我们使用它从 Rust 字符串文本构造 HSTRING 引用。 WinRT API 广泛对字符串值使用 HSTRING

  7. 若要下载 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 构造函数。 窗口 箱中的所有对象都遵循 Rust 约定,并将其构造函数命名为

  8. 现在,可以使用 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

  9. 现在,我们可以遍历结果项,让我们只打印标题。 下面还将看到几行额外代码以设置用户代理头,因为有些 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(())
    }
    
  10. 现在,让我们确认我们可以通过单击 运行>运行而不调试 来生成并运行(或按 Ctrl+F5)。 如果出现任何意外的消息,请确保已成功完成 Hello, world! 教程(Rust with VS Code)

    还有 调试运行 命令嵌入在文本编辑器中。 或者,在rss_reader文件夹的命令提示符中键入cargo run,这将构建并运行程序。

    文本编辑器中嵌入的“调试”和“运行”命令

    在 VS Code 终端 窗格中,你可以看到 Cargo 已成功下载和编译 windows crate,缓存结果,并利用它们在更短的时间内完成后续生成。 然后,它会生成示例并运行该示例,并显示博客文章标题的列表。

    博客文章标题列表

这与为 Windows 编程 Rust 一样简单。 在幕后,投入了大量精力来开发工具,以便 Rust 能够基于 .winmd(公共语言基础结构,或 CLI)正确解析 文件,并在运行时忠实地遵循基于 COM 的应用程序二进制接口(ABI),同时兼顾安全性和效率。

显示消息框

我们确实说,Rust for Windows 允许你调用任何 Windows API(过去、现在和将来)。 因此,在本部分中,我们将显示几个 Windows 消息框。

  1. 就像我们对 RSS 项目所做的那样,在命令提示符下输入 cd,切换到包含 Rust 项目的文件夹。

  2. 创建名为 message_box的新项目,并在 VS Code 中打开它:

    > cargo new message_box
    >     Created binary (application) `message_box` package
    > cd message_box
    > code .
    
  3. 在 VS Code 中打开 Cargo.toml,然后为该项目添加 Windows 依赖项。

     # message_box\Cargo.toml
     ...
    
     [dependencies.windows]
     version = "0.43.0"
     features = [
         "Win32_Foundation",
         "Win32_UI_WindowsAndMessaging",
     ]
    
  4. 现在打开项目 src/main.rs 的文件,并使用新命名空间添加 use 声明(如下所示)。 最后添加代码以调用 MessageBoxAMessageBoxW 函数。 Windows API 文档主要是为 C/C++ 编写的,因此将这些文档与 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 字符串字面量创建 LPCSTRLPCWSTR 参数;就像我们使用 h! 宏为 rss_reader创建 HSTRING 一样。 Rust 本地支持 Unicode 和 UTF-8 字符串,因此优先使用带有 W 后缀的宽 Unicode Windows API,而不是带有 A 后缀的 ANSI API。 如果在代码中使用非英语文本,这一点非常重要。

生成和运行时,Rust 会显示两个 Windows 消息框。