Поделиться через


Руководство по читателю RSS (Rust для Windows с VS Code)

В предыдущем разделе представлена Rust для Windows и пакет windows.

Давайте сейчас попробуем язык Rust на платформе Windows, написав простое консольное приложение, которое скачивает заголовки записей блога из RSS-ленты.

  1. Запустите командную строку (cmd.exe) и cd в папку, в которой вы хотите сохранить проекты Rust.

  2. С помощью Cargo создайте проект Rust с именем rss_readerи cd в только что созданную папку:

    > cargo new rss_reader
    >     Created binary (application) `rss_reader` package
    > cd rss_reader
    
  3. Затем откройте проект rss_reader в VS Code.

    code .
    
  4. Давайте реализуем основной проект rss_reader. Сначала откройте Cargo.toml файл в корне проекта. Cargo.toml Файл — это текстовый файл, описывающий проект Rust, включая все зависимости, которые у него есть.

    Добавьте зависимость от Windows crate, как показано в приведенном ниже списке. ящик для окон большой. Чтобы обеспечить быстрое время сборки, мы выберем только те Foundation_Collections и Web_Syndication функции, которые нам нужны для этого кода.

    # Cargo.toml
    ...
    
    [dependencies.windows] 
    version = "0.43.0"
    features = [
        "Foundation_Collections",
        "Web_Syndication",
    ]
    
  5. Затем откройте файл исходного кода проекта rss_readersrc/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 основной следующим образом:

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

    Обратите внимание, что возвращаемый тип основной функции — это Resultиз windows::core::. Это облегчит работу, так как часто возникают ошибки из API операционной системы (ОС). windows::core::Result помогает нам с распространением ошибок и краткой обработкой ошибок.

    Вы можете видеть оператор вопросительного знака в конце строки кода. Чтобы сократить объем набора текста, мы используем логику распространения и короткого замыкания ошибок в Rust. Это означает, что нам не нужно обрабатывать вручную множество ошибок для этого простого примера. Дополнительные сведения об этой функции Rust см. в разделе оператор ? для упрощения обработки ошибок.

    Также обратите внимание на h! макрос из Windows крейт. Мы используем это для создания ссылки HSTRING на строковый литерал Rust. API WinRT широко использует 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. Все объекты в крейте windows следуют соглашению Rust и называют свои конструкторы new.

  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). Если вы видите неожиданные сообщения, убедитесь, что вы успешно завершили Привет, мир! учебник (Rust с VS Code).

    В текстовом редакторе также есть команды отладка и запуск, встроенные в текст. Кроме того, в командной строке в папке rss_reader введите cargo run, который сначала соберет программу, а затем запустит её.

    Команды отладки и выполнения, внедренные в текстовый редактор

    В нижней панели терминала VS Code можно увидеть, что Cargo успешно скачивает и компилирует windows пакет, кэширует результаты и использует их для выполнения последующих сборок в более короткие сроки. Затем он создает пример и запускает его, отображая список заголовков записей блога.

    Список заголовков записей блога

Это так же просто, как и программа Rust для Windows. Однако под капотом в создание инструментов вкладывается много усилий и внимания, чтобы Rust мог анализировать файлы .winmd на основе ECMA-335 (инфраструктура общего языка, или CLI), а также корректно соблюдать двоичный интерфейс приложения на основе COM (ABI) во время выполнения с учетом безопасности и эффективности.

Отображение поля сообщения

Мы сказали, что Rust для Windows позволяет вызывать любой API Windows (прошлый, нынешний и будущий). Поэтому в этом разделе мы покажем несколько окон сообщений 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 с новыми пространствами имен (как показано ниже). Наконец, добавьте код для вызова функций MessageBoxA и MessageBoxW. Документация по API Windows в основном написана с учетом C/C++, поэтому полезно сравнить документы API с документацией по проекциям Rust в окнах crate: 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);
        }
    }
    

    Как видно, мы должны использовать эти API Win32 в блоке unsafe (см. небезопасные блоки). Кроме того, обратите внимание на макросы s! и w!, которые создают аргументы LPCSTR и LPCWSTR из строковых литералов Rust UTF-8; аналогично тому, как мы создали HSTRING, используя макрос h! для rss_reader. Rust изначально поддерживает Unicode со строками в формате UTF-8, поэтому использование широких Unicode API Windows (W-suffix) предпочтительнее, чем ANSI API (A-suffix). Это может быть важно, если в коде используется не английский текст.

На этот раз при сборке и запуске Rust отображает два поля сообщений Windows.