Compartilhar via


Tutorial do leitor do RSS (Rust para Windows com VS Code)

O tópico anterior introduziu Rust para Windows e o crate de janelas.

Agora vamos experimentar o Rust para Windows escrevendo um aplicativo de console simples que baixa os títulos de postagens de blog de um feed RSS (Really Simple Syndication).

  1. Abra um prompt de comando (cmd.exe) e cd para uma pasta onde você deseja manter seus projetos Rust.

  2. Usando o Cargo, crie um novo projeto Rust chamado rss_readere cd para a pasta recém-criada:

    > cargo new rss_reader
    >     Created binary (application) `rss_reader` package
    > cd rss_reader
    
  3. Em seguida, abra o projeto rss_reader no VS Code.

    code .
    
  4. Vamos implementar o projeto principal rss_reader. Primeiro, abra o Cargo.toml arquivo na raiz do projeto. Um Cargo.toml arquivo é um arquivo de texto que descreve um projeto em Rust, incluindo as dependências que ele tem.

    Adicione uma dependência nas janelas crate, conforme mostrado na listagem abaixo. A caixa de janelas é grande. Para manter os tempos de build rápidos, selecionaremos apenas as características Foundation_Collections e Web_Syndication necessárias para este código.

    # Cargo.toml
    ...
    
    [dependencies.windows] 
    version = "0.43.0"
    features = [
        "Foundation_Collections",
        "Web_Syndication",
    ]
    
  5. Em seguida, abra o arquivo de código-fonte do src/main.rs projeto. Lá, você encontrará o código padrão "Olá, mundo!" do Cargo. Adicione a seguinte instrução use ao início do main.rs:

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

    O uso da declaração reduz o caminho para os tipos que usaremos. Há o tipo de Uri que mencionamos anteriormente.

  6. Para criar uma novade Uri , substitua a função de principal padrão do Cargo por esta:

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

    Observe que o tipo de retorno da função de principal do é umde Resultado , de windows::core::. Isso facilitará as coisas, pois é comum lidar com erros de APIs do sistema operacional (SO). windows::core::Result nos auxilia na propagação de erros e em um tratamento mais conciso desses problemas.

    Você pode ver o operador de ponto de interrogação no final da linha de código. Para economizar na digitação, fazemos isso para usar a lógica de propagação de erros e curto-circuito do Rust. Isso significa que não precisamos fazer um monte de tratamento manual de erros para este exemplo simples. Para obter mais informações sobre esse recurso do Rust, consulte O operador ? para facilitar o tratamento de erros.

    Observe também o h! macro das janelas crate. Usamos isso para construir uma referência de HSTRING a partir de um literal de string Rust. A API do WinRT usa HSTRING extensivamente para valores de cadeia de caracteres.

  7. Para baixar o feed RSS, criaremos um novo SyndicationClient.

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

    A função nova é um construtor em Rust. Todos os objetos no crate windows seguem a convenção Rust e nomeiam seus construtores new.

  8. Agora podemos usar o SyndicationClient para recuperar o 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(())
    }
    

    Como RetrieveFeedAsync é uma API assíncrona, usamos a função de obtenção de bloqueio para manter o exemplo simples. Como alternativa, poderíamos usar o await operador dentro de uma async função para aguardar cooperativamente os resultados. Um aplicativo mais complexo com uma interface gráfica do usuário frequentemente usará async.

  9. Agora podemos iterar sobre os itens resultantes e imprimir apenas os títulos. Você também verá algumas linhas extras de código abaixo para definir um cabeçalho de agente de usuário, já que alguns feeds RSS exigem isso.

    // 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. Agora, vamos confirmar se podemos compilar e executar clicando em Executar>Executar sem Depuração (ou pressionando Ctrl+F5). Se você vir mensagens inesperadas, verifique se concluiu com êxito o tutorial Olá, mundo! (Rust com VS Code).

    Também há comandos Depurar e Executar inseridos no editor de texto. Como alternativa, a partir de um prompt de comando na pasta rss_reader, digite cargo run, que irá compilar e executar o programa.

    Os comandos Depurar e Executar inseridos no editor de texto

    No painel terminal do VS Code , você pode ver que o Cargo baixa e compila com êxito as janelas engradado, armazenando os resultados em cache e usando-os para concluir as compilações subsequentes em menos tempo. Em seguida, ele cria o exemplo e o executa, exibindo uma lista de títulos de postagem no blog.

    Lista de títulos de postagem no blog

Isso é tão simples quanto é programar o Rust para Windows. Por trás das cenas, no entanto, há muito cuidado na criação das ferramentas para que o Rust possa analisar arquivos .winmd com base no ECMA-335 (Common Language Infrastructure, ou CLI), e também respeitar fielmente a interface binária de aplicativo (ABI) baseada em COM durante o tempo de execução, sempre considerando segurança e eficiência.

Mostrando uma caixa de mensagem

Dissemos que o Rust para Windows permite que você chame qualquer API do Windows (passado, presente e futuro). Portanto, nesta seção, mostraremos algumas caixas de mensagem do Windows.

  1. Assim como fizemos para o projeto RSS, no prompt de comando, execute cd para a pasta com seus projetos do Rust.

  2. Crie um novo projeto chamado message_box e abra-o no VS Code:

    > cargo new message_box
    >     Created binary (application) `message_box` package
    > cd message_box
    > code .
    
  3. No VS Code, abra o Cargo.toml, e então adicione as dependências do Windows para este projeto:

     # message_box\Cargo.toml
     ...
    
     [dependencies.windows]
     version = "0.43.0"
     features = [
         "Win32_Foundation",
         "Win32_UI_WindowsAndMessaging",
     ]
    
  4. Agora, abra o arquivo do src/main.rs projeto e adicione as use declarações com os novos namespaces (conforme mostrado abaixo). E, por fim, adicione código para chamar as funções MessageBoxA e MessageBoxW . Os documentos da API do Windows são escritos principalmente com C/C++ em mente, portanto, é útil comparar os documentos da API com os documentos das projeções do Rust nas janelas crate: do MessageBoxA (Rust) e 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);
        }
    }
    

    Como você pode ver, devemos usar essas APIs Win32 em um unsafe bloco (consulte blocos não seguros). Observe também os macros s! e w!, que criam argumentos LPCSTR e LPCWSTR a partir de literais de cadeia de caracteres Rust UTF-8; assim como criamos uma HSTRING com o macro h! para rss_reader. O Rust é, nativamente, Unicode com cadeias de caracteres UTF-8, portanto, usar as APIs amplas do Windows Unicode (sufixo W) é preferencial em vez das APIs ANSI (Sufixo A). Isso pode ser importante se você usar texto não inglês em seu código.

Desta vez, quando você cria e executa, o Rust exibe duas caixas de mensagem do Windows.