Catégories

Applications Windows Universelles avec C++WinRT à partir d’un projet vide

Pour comprendre de quoi il s’agit il est préférable d’avoir lu cette page.

J’imagine ici que j’ai l’intention d’écrire un bout de code qui utilise C++WinRT mais sans interface graphique. Cela peut être le cas si je veux faire un test par exemple. Je souhaite pourtant utiliser un projet Visual Studio pour pouvoir gentiment travailler dans l’environnement de travail (debug par exemple). Que faire? Refaire ce que nous avions fait dans l’article précédent n’est pas entièrement satisfaisant. En effet, déshabiller un projet C++/CX & XAML laisse des ressources sur le disque (les images .png) que l’on utilisera jamais. En plus, il doit y avoir 12 millions de paramètres positionnés pour nous et dont on ne sait rien. Bref, partir de zéro nous permettra de bien comprendre le processus du Build et de maîtriser les fichiers ainsi que leur organisation sur le disque. Allez c’est parti.

J’ouvre Visual Studio. Ensuite CTRL+SHIFT+N et je choisis Templates/Visual C++/Empty Project. Je vous laisse choisir le nom du fichier et l’endroit où vous allez le sauvegarder.

Bon normalement cela ne doit pas prendre trois heures… À droite dans le répertoire Source Files, je clique droit et je choisis Add puis New Item...

Là je demande à ajouter un fichier cpp que je nomme MyApp.cpp. Ensuite je vais suivre la même procédure (ou j’utilise CTRL+SHIFT+A pour aller plus vite) et j’ajoute un fichier header que je nome pch.h et un fichier source que je nomme pch.cpp. À la fin l’arborescence ressemble à ceci :

On va commencer par le plus simple et régler la précompilation des fichiers header. En effet il ne faut pas oublier que cppwinrt est entièrement basé sur des fichiers header et qu’on a donc intérêt à éviter de tout compiler à chaque fois. À gauche, dans Solution Explorer je clique donc sur le nom du projet puis j’appuie sur ALT+ENTER. La fenêtre des propriétés du projet apparaît à l’écran. Je vais dans C/C++ puis dans Precompiled Header.

Là je fais bien attention à ce que les listes en haut soient positionnées sur All Configurations et sur All Platforms.

Ensuite je vais dans C/C++ et je clique sur Precompiled Header. Là je fais en sorte que :

  1. l’option Precompiled Header soit sur Use (/Yu)
  2. l’option Precompiled Header File pointe sur le fichier pch.h.

Voir ci-dessous :

Dans le fichier pch.cpp il suffit ensuite de copier la ligne de code suivante :

#include "pch.h"

Quand c’est fait, je vais sur le fichier pch.cpp, je clique dessus et j’appuie sur ALT+ENTER pour faire apparaître la boîte de propriétés. Je fais bien attention à ce que les listes en haut soit sur All Configurations et sur All Platforms.

Ensuite je vais dans C/C++ et je clique sur Precompiled Header et je fais en sorte que :

  1. l’option Precompiled Header soit sur Create (/Yc)
  2. l’option Precompiled Header File pointe sur le fichier pch.h.

Voir ci-dessous :

En cas de doute sur ces histoires de fichiers précompilés allez jeter un oeil sur cette page.

Bon allez, on passe à la suite. Là on va pas perdre de temps et on va faire du copier coller. Allez dans le répertoire Samples de cppwinrt. Normalement il est dans ../cppwinrt/10.0.14393.0/Samples. Là vous allez dans le répertoire Syndication et vous ouvrez dans Notepad le fichier Main.cpp. Quand vous l’avez sous les yeux vous faites un bon vieux CTRL+A puis CTRL+C et vous retournez dans Visual Studio et vous copiez le code dans MyApp.cpp. Histoire d’assurer voilà le code :

#include "pch.h"

using namespace winrt;

using namespace Windows::Foundation;
using namespace Windows::Web::Syndication;

IAsyncAction Sample()
{
    Uri uri(L"http://kennykerr.ca/feed");
    SyndicationClient client;
    SyndicationFeed feed = co_await client.RetrieveFeedAsync(uri);

    for (SyndicationItem item : feed.Items())
    {
        hstring title = item.Title().Text();

        printf("%ls\n", title.c_str());
    }
}

int main()
{
    initialize();
    Sample().get();
}

Encore une fois, je ne vais pas ici expliquer le code car ce n’est pas l’objet de l’article. Moi ce que je veux c’est compiler 🙂

Quand c’est fait, on fait la même chose avec le contenu du fichier ../cppwinrt/10.0.14393.0/Samples/Syndication/pch.h que l’on colle dans notre fichier pch.h. Voilà le contenu du ficher en question :

#pragma once

#pragma comment(lib, "windowsapp") 

#include "winrt/Windows.Foundation.h"
#include "winrt/Windows.Web.Syndication.h"

Là, normalement on voit déjà qu’il y a un problème. En effet, notre code fait des vagues…

Si on approche le curseur des vaguelettes rouge, Visual nous dit qu’il ne sait pas comment pointer sur winrt/Windows.Web.Syndication.h

Ça, ça sent le problème de chemin d’accès aux fichiers include qu’on a déjà vu la fois précédente. Je vais donc aller un peut plus vite ici

  1. Clic sur le nom du projet
  2. ALT+ENTER
  3. All Conf & All Platforms
  4. C/C++
  5. General
  6. Additional Include Directories doit pointer sur un truc du style « blablabla\cppwinrt\cppwinrt\10.0.14393.0« 
  7. On en profite pour mettre le Warning Level à 4

Voir ci-dessous :

On clique sur Appliquer puis sur OK et on revient dans l’éditeur. Normalement il n’y a plus de vagues sous les include. Si on ouvre le fichier MyApp.cpp là on trouve d’autres vagues sous co_wait par exemple. Ça, ça doit me faire penser que je doit utiliser des options expérimentales du compilateur (voir article précédent) pour compiler les sources. Là aussi je vais me permettre d’aller plus vite :

  1. Clic sur le projet
  2. ALT+ENTER
  3. All Conf & All Platforms
  4. C/C++
  5. Command Line
  6. Là je tape : /await /std:c++latest

Voir ci-dessous :

On clique sur Appliquer puis sur OK et on revient dans l’éditeur.

Bonne nouvelle. À ce stade on peut compiler le code MyApp.cpp. Allez, j’appuie sur CTRL+F7. Normalement ça doit compiler sans erreur.

Bon allez on va générer l’exécutable… J’appuie sur CTRL+SHIFT+B et là ça part en vrille ! Il y a deux messages d’erreur (Faut pas hésiter à cliquer sur l’image ci-dessous si c’est pas lisible)

Ce qui me fait tiquer c’est le message concernant windowsapp.lib. Allez, on retourne dans les propriétés du projet et là je vais dans General (tout en haut de la boite de dialogue). À droite j’observe que l’option Target Platform Version est fixé à 8.1. Je déroule la liste box et je choisi 10.0.14393.0. Je clique sur OK et de retour dans l’éditeur je relance une compilation et une édition de lien en appuyant sur CTRL+SHIFT+B. Et là tout roule !

Je pose un point d’arrêt sur la ligne 18 (printf()) et le lance le code en appuyant sur F5. Après je m’amuse et je clique sur F10 pour circuler dans la boucle. Que du bonheur.

Remarque

Si je lance le code sans point d’arrêt, la console disparaît tout de suite et je ne vois rien. Pour corriger cela je propose de modifier le code comme suit :

#include "pch.h"

using namespace winrt;

using namespace Windows::Foundation;
using namespace Windows::Web::Syndication;

using namespace std;

IAsyncAction Sample()
{
	Uri uri(L"http://kennykerr.ca/feed");
	SyndicationClient client;
	SyndicationFeed feed = co_await client.RetrieveFeedAsync(uri);

	for (SyndicationItem item : feed.Items())
	{
		hstring title = item.Title().Text();

		printf("%ls\n", title.c_str());
	}
}

int main()
{
	initialize();
	Sample().get();

	cout << "Press ENTER to quit : ";
	cin.ignore((numeric_limits<streamsize>::max)(), '\n');
}

Bien sûr pour utiliser std::cout il faut modifier pch.h comme suit :

#pragma once

#pragma comment(lib, "windowsapp") 

#include "winrt/Windows.Foundation.h"
#include "winrt/Windows.Web.Syndication.h"

#include <iostream>

Si on lance le build, tout devrait bien se passer et voilà ce que l’on observe :

Il faut remarquer que Visual est obligé de recompiler le fichier pch.cpp car on a modifié le contenu de pch.h.

Finalement, puisque iostream.h est dans le projet autant en profiter pour virer le printf() de la boucle for et de ré-écrire cette dernière comme suit :

for (SyndicationItem item : feed.Items())
{
	hstring title = item.Title().Text();
	wcout << title.c_str() << "\n";
}

Si on lance un dernier Build voilà ce que l’on obtient en sortie :

On observe bien que Visual ne compile que MyApp.cpp et plus pch.cpp. On a donc la preuve que notre configuration du fichier header précompilé fonctionne bien.

Allez, je crois que c’est bon pour ce soir. A plus.

 

Comments are closed.