共用方式為


RSS 讀取器教學課程 (具有 VS Code 的 Rust for Windows)

上一個主題介紹了 Rust for Windowst 及 windows crate

現在,讓我們透過撰寫一個簡單的主控台應用程式來試用 Rust for Windows,該應用程式可從 Really Simple Syndication (RSS) Feed 下載部落格文章的標題。

  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 專案的文字檔,包括它擁有的任何相依性。

    windows crate 上新增一個相依性,如下列清單所示。 windows crate 很大。 為了保持建置時間快速,我們只會選取此程式碼所需的 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!" 程式碼。 將下列的 use 陳述式新增至 main.rs 的開頭:

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

    use 宣告會縮短我們將使用的類型的路徑。 那裡有我們稍早提到的 Uri 類型。

  6. 若要建立新的 Uri,請使用下列項目來取代 Cargo 的預設 main 函式:

    // src\main.rs
    ...
    
    fn main() -> Result<()> {
        let uri = Uri::CreateUri(h!("https://blogs.windows.com/feed"))?;
    
        Ok(())
    }
    

    請注意,main 函式的傳回類型是一個 Result 類型 (來自 windows::core:: 模組)。 這將使事情變得更容易,因為處理作業系統 (OS) API 中的錯誤是很常見的。 windows::core::Result 可幫助我們進行錯誤傳播和簡潔的錯誤處理。

    您可以在程式碼行結尾看到問號運算子。 為了節省打字時間,我們這樣做是為了使用 Rust 的錯誤傳播和短路邏輯。 這意味著對於這個簡單的例子,我們不必進行大量的手動錯誤處理。 如需此 Rust 功能的詳細資訊,請參閱用於更易於處理錯誤的 ? 運算子

    還要注意來自 windows crate 的 h! 巨集。 我們使用它以從 Rust 字串常值中建構一個 HSTRING 參考。 WinRT API 會廣泛使用 HSTRING 來表示字串值。

  7. 為了下載 RSS Feed,我們將建立一個新的 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

  8. 現在,我們可以使用 SyndicationClient 來擷取該 Feed。

    // 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 函式來讓範例保持簡單。 或者,我們也可以在 async 函式內使用 await 運算子來合作等待結果。 具有圖形化使用者介面的較複雜應用程式通常會使用 async

  9. 現在我們可以逐一查看產生的項目,讓我們只列印出標題。 您也會在下面看到幾行額外的程式碼行,用於設定使用者代理標頭,因為有些 RSS Feed 需要這樣做。

    // 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! 教學課程 (使用 VS Code 來開發 Rust)

    也有 DebugRun 命令內嵌在文字編輯器內。 或者,也可以從 rss_reader 資料夾中的命令提示字元中輸入 cargo run,這會建置並執行程式。

    內嵌在文字編輯器中的 [偵錯] 和 [執行] 命令

    在 VS Code 終端機窗格中,您可以看到 Cargo 成功下載並編譯了 windows crate,進而快取結果,並使用它們以在更短的時間內完成後續的組建。 然後,它會建置範例並加以執行,進而顯示部落格文章標題的清單。

    部落格文章標題清單

這就是編寫 Rust for Windows 的簡單過程。 然而,在幕後,需要大量的精力來建置工具,以便讓 Rust 能夠剖析基於 ECMA-335 (Common Language Infrastructure 或 CLI) 的 .winmd 檔案,同時在執行時忠實地遵循基於 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++ 撰寫的,因此將 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 API (請參閱不安全的區塊)。 還要注意 s!w! 巨集,它們可以從 Rust 的 UTF-8 字串常值建立 LPCSTRLPCWSTR 引數,類似我們使用 h! 巨集為 rss_reader 建立 HSTRING 的方式。 Rust 本身是一種原生支援 Unicode 的語言,使用 UTF-8 字串,因此會優先使用廣泛使用 Unicode (帶有 W 尾碼) 的 Windows API,而不是 ANSI (帶有 A 尾碼) 的 API。 如果您在程式碼中使用非英文文字,這一點可能很重要。

這次當您建置並執行時,Rust 會顯示兩個 Windows 訊息方塊。