Partager via


Tutoriel sur le lecteur RSS (Rust pour Windows avec VS Code)

Dans la rubrique précédente, nous avons découvert Rust pour Windows et la crate windows.

Essayons à présent Rust pour Windows en écrivant une application console simple qui télécharge les titres de billets de blog à partir d’un flux RSS (Really Simple Syndication).

  1. Lancez une invite de commandes (cmd.exe) et exécutez cd pour accéder au dossier où vous souhaitez conserver vos projets Rust.

  2. Avec Cargo, créez un projet Rust nommé rss_reader et exécutez cd pour accéder au dossier nouvellement créé :

    > cargo new rss_reader
    >     Created binary (application) `rss_reader` package
    > cd rss_reader
    
  3. Ouvrez ensuite le projet rss_reader dans VS Code.

    code .
    
  4. Implémentons le projet rss_reader principal. Tout d’abord, ouvrez le fichier Cargo.toml à la racine du projet. Un fichier Cargo.toml est un fichier texte qui décrit un projet Rust, notamment toutes ses dépendances.

    Ajoutez une dépendance sur le crate windows, comme indiqué dans la liste ci-dessous. Le crate windows est grand. Pour accélérer les temps de génération, nous allons juste sélectionner les fonctionnalités Foundation_Collections et Web_Syndication dont nous avons besoin pour ce code.

    # Cargo.toml
    ...
    
    [dependencies.windows] 
    version = "0.43.0"
    features = [
        "Foundation_Collections",
        "Web_Syndication",
    ]
    
  5. Ensuite, ouvrez le fichier de code source src/main.rs du projet rss_reader. Vous y trouverez le code Cargo par défaut « Hello, world! ». Ajoutez l’instruction use suivante au début de main.rs :

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

    La déclaration use raccourcit le chemin aux types que nous allons utiliser. Vous trouverez le type Uri que nous avons mentionné précédemment.

  6. Pour créer un URI, remplacez la fonction main par défaut de Cargo par les éléments suivants :

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

    Notez que le type de retour de la fonction main est un Result de windows::core::. Cela facilite les choses, car il est courant d’avoir à gérer les erreurs des API du système d’exploitation. windows::core::Result nous aide avec la propagation des erreurs et permet une gestion concise des erreurs.

    Notez la présence de l’opérateur ? à la fin de la ligne de code. Cet opérateur nous permet de saisir moins de code et d’utiliser la logique de propagation des erreurs et de court-circuit de Rust. Cela signifie que nous n’avons pas à effectuer un grand nombre de tâches manuelles de gestion des erreurs pour cet exemple simple. Pour plus d’informations sur cette fonctionnalité de Rust, consultez L’opérateur ? pour faciliter la gestion des erreurs.

    Notez également la macro h! dans le crate windows. Nous l’utilisons pour construire une référence HSTRING à partir d’un littéral de chaîne Rust. L’API WinRT utilise HSTRING de manière intensive pour les valeurs de chaîne.

  7. Pour télécharger le flux RSS, nous allons créer un SyndicationClient.

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

    La fonction new est un constructeur Rust. Tous les objets du crate windows suivent la convention Rust et nomment leurs constructeurs new.

  8. Maintenant, nous pouvons utiliser SyndicationClient pour récupérer le flux.

    // 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(())
    }
    

    Étant donné que RetrieveFeedAsync est une API asynchrone, nous utilisons la fonction de blocage get pour que l’exemple reste simple. Nous pouvons également utiliser l’opérateur await dans une fonction async pour attendre de manière coopérative les résultats. Une application plus complexe avec une interface graphique utilisateur emploie fréquemment async.

  9. À présent, nous pouvons itérer au sein des éléments résultants et imprimer uniquement les titres. Vous verrez également quelques lignes de code supplémentaires ci-dessous pour définir un en-tête user-agent, car certains flux RSS l’exigent.

    // 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. Vérifions maintenant que nous pouvons générer et exécuter notre exemple. Pour cela, cliquez sur Exécuter>Exécuter sans débogage (ou appuyez sur Ctrl+F5). Si vous voyez des messages inattendus, vérifiez que vous avez bien terminé le tutoriel Hello, world! (Rust avec VS Code).

    Des commandes Déboguer et Exécuter sont également intégrées à l’éditeur de texte. Vous pouvez également, à partir d’une invite de commandes dans le dossier rss_reader, taper cargo run, qui générera et exécutera le programme.

    Commandes Déboguer et Exécuter intégrées à l’éditeur de texte

    Dans le volet Terminal de VS Code, vous pouvez voir que Cargo télécharge et compile correctement le crate Windows. Les résultats sont mis en cache, ce qui permet de générer les prochaines builds en moins de temps. Il génère ensuite l’exemple, l’exécute et affiche une liste de titres de billets de blog.

    Liste de titres de billets de blog

Programmer avec Rust pour Windows, c’est aussi simple que cela ! Toutefois, en arrière-plan, beaucoup d’efforts ont été faits pour créer des outils grâce auxquels Rust peut non seulement analyser les fichiers .winmd selon la norme ECMA-335 (Common Language Infrastructure ou CLI), mais aussi honorer fidèlement l’ABI (Application Binary Interface) basée sur COM au moment de l’exécution, le tout de manière sécurisée et efficace.

Afficher une boîte de message

Nous avons vu que Rust pour Windows vous permet d’appeler n’importe quelle API Windows (passée, présente et future). Par conséquent, dans cette section, nous allons montrer quelques messages Windows.

  1. Comme nous l’avons fait pour le projet RSS, à l’invite de commandes, exécutez cd pour accéder au dossier contenant vos projets Rust.

  2. Créez un projet appelé message_box et ouvrez-le dans VS Code :

    > cargo new message_box
    >     Created binary (application) `message_box` package
    > cd message_box
    > code .
    
  3. Dans VS Code, ouvrez Cargo.toml et ajoutez les dépendances Windows pour ce projet :

     # message_box\Cargo.toml
     ...
    
     [dependencies.windows]
     version = "0.43.0"
     features = [
         "Win32_Foundation",
         "Win32_UI_WindowsAndMessaging",
     ]
    
  4. Ouvrez maintenant le fichier src/main.rs du projet, puis ajoutez les déclarations use avec les nouveaux espaces de noms (comme montré ci-dessous). Enfin, ajoutez du code pour appeler les fonctions MessageBoxA et MessageBoxW. La documentation des API Windows est essentiellement écrite en pensant à C/C++. Il est donc utile de comparer la documentation des API à la documentation des projections Rust dans le crate windows : MessageBoxA (Rust) et 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);
        }
    }
    

    Comme vous pouvez le voir, nous devons utiliser ces API Win32 dans un unsafe bloc (voir Blocs non sécurisés). Notez également les macros s! et w!, qui créent les arguments LPCSTR et LPCWSTR à partir des littéraux de chaîne Rust UTF-8, tout comme nous avons créé un HSTRING avec la macro h! pour rss_reader. Rust étant nativement Unicode avec des chaînes UTF-8, l’utilisation des grandes API Windows Unicode (suffixe W) est préférable aux API ANSI (suffixe A). Cela peut être important si vous utilisez du texte non anglais dans votre code.

Cette fois-ci, lorsque vous générez et exécutez, Rust affiche deux messages Windows.