Tutorial do leitor de RSS (Rust para Windows com VS Code)
O tópico anterior apresentou o Rust para Windows e o crate windows.
Agora vamos experimentar o Rust para Windows ao gravar um aplicativo de console simples que baixa os títulos de postagens de blog de um feed RSS (Really Simple Syndication).
Inicialize um prompt de comando (
cmd.exe
) ecd
para uma pasta onde você deseja manter seus projetos do Rust.Usando o Cargo, crie um projeto do Rust chamado rss_reader e
cd
na pasta recém-criada:> cargo new rss_reader > Created binary (application) `rss_reader` package > cd rss_reader
Em seguida, abra o projeto rss_reader no VS Code.
code .
Vamos implementar o projeto principal rss_reader. Primeiro, abra o arquivo
Cargo.toml
na raiz do projeto. Um arquivoCargo.toml
é um arquivo de texto que descreve um projeto do Rust, incluindo as dependências dele.Adicione uma dependência ao crate windows, conforme mostrado na listagem abaixo. O crate windows é grande. Para manter os tempos de build rápidos, selecionaremos apenas os recursos
Foundation_Collections
eWeb_Syndication
necessários para esse código.# Cargo.toml ... [dependencies.windows] version = "0.43.0" features = [ "Foundation_Collections", "Web_Syndication", ]
Depois, abra o arquivo de código-fonte
src/main.rs
do projeto rss_reader. Lá, você encontrará o código "Olá, mundo!" padrão do Cargo. Adicione a seguinte instrução use ao início demain.rs
:// src\main.rs use windows::{ core::*, Foundation::Uri, Web::Syndication::SyndicationClient }; fn main() { println!("Hello, world!"); }
A declaração use reduz o caminho para os tipos que usaremos. Há o tipo Uri que mencionamos anteriormente.
Para criar um Uri, substitua a função main 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 main é um Resultado, com base em windows::core::. Isso facilitará tudo, pois é comum lidar com erros de APIs do SO (sistema operacional). O windows::core::Result nos ajuda com a propagação de erros e com o tratamento de erro conciso.
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 utilizar a lógica de propagação de erro e curto-circuito do Rust. Isso significa que não precisamos fazer muito tratamento de erro manual para este exemplo simples. Para obter mais informações sobre esse recurso do Rust, consulte O operador ? para obter um tratamento de erros mais fácil.
Observe também a macro h! do crate windows. Usamos isso para construir uma referência HSTRING com base em um literal de cadeia de caracteres Rust. A API do WinRT usa o HSTRING extensivamente para valores de cadeia de caracteres.
Para baixar este feed RSS, criaremos um objeto 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 new é um construtor Rust. Todos os objetos no crate windows seguem a convenção Rust e nomeiam os construtores deles como new.
Agora, podemos usar 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 bloqueio get para manter o exemplo simples. Como alternativa, poderíamos usar o operador
await
dentro de uma funçãoasync
para aguardar os resultados de forma cooperativa. Um aplicativo mais complexo com uma interface do usuário gráfica usaráasync
com frequência.Podemos iterar nos 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 RSS feeds 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(()) }
Vamos confirmar que podemos criar 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 Debug e Run inseridos dentro do editor de texto. Como alternativa, em um prompt de comando na pasta
rss_reader
, digitecargo run
, que será criado e, em seguida, executará o programa.Na parte inferior do painel Terminal do VS Code, você pode ver que o Cargo baixa e compila com êxito o crate windows, armazenando em cache os resultados e usando-os para fazer com que as compilações subsequentes sejam concluídas em menos tempo. Em seguida, ele compila o exemplo e executa-o, exibindo uma lista de títulos de postagem de blog.
Isso é tão simples quanto programar o Rust para Windows. Mas, no fundo, grande parte da simplicidade consiste em criar as ferramentas para que o Rust possa analisar arquivos .winmd
com base em ECMA-335 (Common Language Infrastructure ou CLI) e também usar de forma segura a ABI (interface binária de aplicativos) baseada em COM em tempo de execução, sempre colocando a segurança e a eficiência em primeiro lugar.
Mostrar uma caixa de mensagem
Dissemos que o Rust para Windows permite que você chame qualquer API do Windows (antiga, atual e futura). Portanto, nesta seção, mostraremos algumas caixas de mensagens do Windows.
Assim como fizemos no projeto RSS, no prompt de comando
cd
para a pasta com seus projetos do Rust.Crie um projeto chamado message_box e abra-o no VS Code:
> cargo new message_box > Created binary (application) `message_box` package > cd message_box > code .
No VS Code, abra o
Cargo.toml
e 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", ]
Agora abra o arquivo
src/main.rs
do projeto e adicione as declaraçõesuse
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 principalmente escritos com C/C++ em mente, então é útil comparar os documentos da API com os documentos para as projeções do Rust no crate windows: 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, precisamos usar essas APIs Win32 em um bloco
unsafe
(confira Blocos não seguros). Observe também as macros s! e w!, que criam argumentos LPCSTR e LPCWSTR de literais de cadeia de caracteres UTF-8 Rust; assim como criamos um HSTRING com a macro h! para rss_reader. O Rust é, nativamente, um Unicode com cadeias de caracteres UTF-8, portanto, o usdo das APIs amplas do Windows Unicode (sufixo W) é preferencial ao das APIs ANSI (sufixo A). Isso poderá ser importante se você usar texto não inglês em seu código.
Dessa vez, ao criar e executar, o Rust exibe duas caixas de mensagens do Windows.
Relacionados
Windows developer