Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
À mesure que les versions suivantes de C++/WinRT sont publiées, cette rubrique décrit les nouveautés et les modifications apportées.
Cumul des améliorations/ajouts récents à compter de mars 2020
Des temps de génération jusqu’à 23 % plus courts
Les équipes du compilateur C++/WinRT et C++ ont collaboré pour faire tout ce qui est possible pour raccourcir les temps de génération. Nous avons parcouru l’analytique du compilateur pour déterminer comment les internes de C++/WinRT peuvent être restructurés pour aider le compilateur C++ à éliminer la surcharge au moment de la compilation, ainsi que la façon dont le compilateur C++ lui-même peut être amélioré pour gérer la bibliothèque C++/WinRT. C++/WinRT a été optimisé pour le compilateur ; et le compilateur a été optimisé pour C++/WinRT.
Prenons par exemple le pire cas de figure consistant à générer un en-tête précompilé (PCH) qui contient tous les fichiers d’en-tête des espaces de noms de projection C++/WinRT.
| Version | Taille du PCH (octets) | Heure (s) |
|---|---|---|
| C++/WinRT à partir de juillet, avec Visual C++ 16.3 | 3,004,104,632 | 31 |
| version 2.0.200316.3 de C++/WinRT, avec Visual C++ 16.5 | 2,393,515,336 | 24 |
Une réduction de la taille de 20% et une réduction de 23% du temps de génération.
Prise en charge améliorée de MSBuild
Nous avons investi beaucoup de travail dans l’amélioration de la prise en charge de MSBuild pour une grande sélection de différents scénarios.
Mise en cache en usine encore plus rapide
Nous avons amélioré l’intégration en ligne du cache de fabrique afin de mieux intégrer en ligne les chemins d’exécution les plus fréquents, ce qui accélère l’exécution.
Cette amélioration n'affecte pas la taille du code, comme décrit ci-dessous dans Optimized EH code-gen, si votre application utilise fortement la gestion des exceptions C++, vous pouvez réduire votre binaire à l'aide de l/d2FH4'option, qui est activée par défaut dans les nouveaux projets créés avec Visual Studio 2019 16.3 et versions ultérieures.
Boxe plus efficace
Lorsqu’elle est utilisée dans une application XAML, winrt ::box_value est désormais plus efficace (voir Boxing et unboxing). Les applications qui font beaucoup de boxe remarqueront également une réduction de la taille du code.
Prise en charge de l’implémentation d’interfaces COM qui implémentent IInspectable
Si vous devez implémenter une interface COM (non-Windows-Runtime) qui implémente également IInspectable, vous pouvez désormais le faire avec C++/WinRT. Consultez les interfaces COM qui implémentent IInspectable.
Améliorations du verrouillage des modules
Le contrôle du verrouillage de module permet désormais à la fois des scénarios d’hébergement personnalisés et l’élimination totale du verrouillage au niveau du module. Consultez les améliorations apportées au verrouillage de module.
Prise en charge des informations d’erreur non-Windows Runtime
Certaines API (même certaines API Windows Runtime) signalent des erreurs sans utiliser Windows Runtime API d’origine des erreurs. Dans ce cas, C++/WinRT revient désormais à utiliser les informations d’erreur COM. Consultez la prise en charge des informations d’erreur non-WinRT dans C++/WinRT.
Activer la prise en charge du module C++
La prise en charge des modules C++ est de retour, mais uniquement sous une forme expérimentale. La fonctionnalité n’est pas encore terminée dans le compilateur C++.
Reprise coroutine plus efficace
Les coroutines C++/WinRT fonctionnent déjà bien, mais nous continuons à rechercher des moyens d’améliorer cela. Consultez Améliorer l’extensibilité de la reprise de coroutine.
Nouveaux utilitaires asynchrones when_all et when_any
La fonction utilitaire when_all crée un objet IAsyncAction qui s’achève lorsque tous les éléments awaitables fournis sont terminés. La fonction utilitaire when_any crée une IAsyncAction qui se termine dès que l’une des opérations pouvant être attendues fournies est terminée.
Consultez Ajouter l’utilitaire asynchrone when_any et Ajouter l’utilitaire asynchrone when_all.
Autres optimisations et ajouts
De plus, de nombreux correctifs de bogues et optimisations mineures et ajouts ont été introduits, notamment diverses améliorations pour simplifier le débogage et optimiser les implémentations internes et par défaut. Suivez ce lien pour obtenir une liste exhaustive : https://github.com/microsoft/xlang/pulls?q=is%3Apr+is%3Aclosed.
Actualités et modifications, en C++/WinRT 2.0
Pour plus d’informations sur l’extension Visual Studio C++/WinRT (VSIX), le package NuGet Microsoft.Windows.CppWinRT et l’outil cppwinrt.exe — y compris sur la façon de les obtenir et de les installer —, consultez Prise en charge de C++/WinRT, de XAML, de l’extension VSIX et du package NuGet dans Visual Studio.
Modifications apportées à l’extension de Visual Studio C++/WinRT (VSIX) pour la version 2.0
- Le visualiseur de débogage prend désormais en charge Visual Studio 2019, tout en continuant à prendre en charge Visual Studio 2017.
- De nombreux correctifs de bogues ont été effectués.
Modifications apportées au package NuGet Microsoft.Windows.CppWinRT pour la version 2.0
- L’outil
cppwinrt.exeest désormais inclus dans le package NuGet Microsoft.Windows.CppWinRT, et il génère à la demande des en-têtes de projection de plateforme pour chaque projet. Par conséquent, l’outilcppwinrt.exene dépend plus du sdk Windows (bien que l’outil soit toujours fourni avec le KIT SDK pour des raisons de compatibilité). -
cppwinrt.exegénère désormais des en-têtes de projection dans chaque dossier intermédiaire ($IntDir) propre à la plateforme et à la configuration afin de permettre les compilations parallèles. - La prise en charge des builds C++/WinRT (props/targets) est désormais entièrement documentée, au cas où vous souhaitez personnaliser manuellement vos fichiers projet. Consultez le fichier readme du package NuGet Microsoft.Windows.CppWinRT.
- De nombreux correctifs de bogues ont été effectués.
Modifications apportées à C++/WinRT pour la version 2.0
Open source
L’outil cppwinrt.exe prend un fichier de métadonnées Windows Runtime (.winmd) et génère à partir de celui-ci une bibliothèque C++ standard basée sur un fichier d’en-tête qui projette les API décrites dans les métadonnées. Ainsi, vous pouvez utiliser ces API à partir de votre code C++/WinRT.
Cet outil est désormais un projet entièrement open source disponible sur GitHub. Visitez Microsoft/cppwinrt.
Bibliothèques xlang
Une bibliothèque d’en-têtes uniquement portable (pour analyser le format de métadonnées ECMA-335 utilisé par le Windows Runtime) constitue la base de tous les outils Windows Runtime et xlang à l’avenir. À noter que nous avons également réécrit l’outil cppwinrt.exe de fond en comble à l’aide des bibliothèques xlang. Cela fournit des requêtes de métadonnées beaucoup plus précises, en résolvant quelques problèmes de longue date avec la projection de langage C++/WinRT.
Moins de dépendances
En raison du lecteur de métadonnées xlang, l’outil cppwinrt.exe lui-même a moins de dépendances. Cela le rend bien plus flexible et permet de l’utiliser dans davantage de scénarios, en particulier dans des environnements de build contraints. Notamment, il ne s’appuie plus sur RoMetadata.dll.
Il s’agit des dépendances de cppwinrt.exe 2.0.
- ADVAPI32.dll
- KERNEL32.dll
- SHLWAPI.dll
- XmlLite.dll
Toutes ces DLL sont disponibles non seulement sur Windows 10, mais jusqu’à Windows 7, et même Windows Vista. Si vous le souhaitez, votre ancien serveur de build exécutant Windows 7 peut maintenant s’exécuter cppwinrt.exe pour générer des en-têtes C++ pour votre projet. Avec un peu de travail, vous pouvez même exécuter C++/WinRT sur Windows 7, si cela vous intéresse.
Contrastez la liste ci-dessus avec ces dépendances, dont cppwinrt.exe la version 1.0 a.
- ADVAPI32.dll
- SHELL32.dll
- api-ms-win-core-file-l1-1-0.dll
- XmlLite.dll
- api-ms-win-core-libraryloader-l1-2-0.dll
- api-ms-win-core-processenvironment-l1-1-0.dll
- RoMetadata.dll
- SHLWAPI.dll
- KERNEL32.dll
- api-ms-win-core-rtlsupport-l1-1-0.dll
- api-ms-win-core-heap-l1-1-0.dll
- api-ms-win-core-timezone-l1-1-0.dll
- api-ms-win-core-console-l1-1-0.dll
- api-ms-win-core-localization-l1-2-0.dll
- OLEAUT32.dll
- api-ms-win-core-winrt-error-l1-1-0.dll
- api-ms-win-core-winrt-error-l1-1-1.dll
- api-ms-win-core-winrt-l1-1-0.dll
- api-ms-win-core-winrt-string-l1-1-0.dll
- api-ms-win-core-synch-l1-1-0.dll
- api-ms-win-core-threadpool-l1-2-0.dll
- api-ms-win-core-com-l1-1-0.dll
- api-ms-win-core-com-l1-1-1.dll
- api-ms-win-core-synch-l1-2-0.dll
L’attribut Windows Runtime noexcept
Le Windows Runtime a un nouvel [noexcept] attribut, que vous pouvez utiliser pour décorer vos méthodes et propriétés dans MIDL 3.0. La présence de l’attribut indique aux outils de prise en charge que votre implémentation ne lève pas d’exception (ni retourne un HRESULT défaillant). Cela permet aux projections de langage d’optimiser la génération de code en évitant la surcharge de gestion des exceptions requise pour prendre en charge les appels d’interface binaire d’application (ABI) qui peuvent potentiellement échouer.
C++/WinRT tire parti de cela en produisant des implémentations C++ noexcept à la fois du code client et du code d’implémentation. Si vous avez des méthodes d’API ou des propriétés sans échec, et que vous êtes préoccupé par la taille du code, vous pouvez examiner cet attribut.
Génération de code optimisée
C++/WinRT génère désormais un code source C++ encore plus efficace (en arrière-plan) afin que le compilateur C++ puisse produire le code binaire le plus petit et le plus efficace possible. Nombre de ces améliorations visent à réduire le coût de la gestion des exceptions en évitant des informations de désempilement inutiles. Les fichiers binaires qui utilisent de grandes quantités de code C++/WinRT verront environ 4% réduction de la taille du code. Le code est également plus efficace (il s’exécute plus rapidement) en raison du nombre d’instructions réduit.
Ces améliorations s’appuient également sur une nouvelle fonctionnalité d’interopérabilité qui vous est également disponible. Tous les types C++/WinRT qui sont propriétaires de ressources incluent désormais un constructeur pour prendre possession directement, évitant ainsi l’approche en deux étapes précédente.
ABI::Windows::Foundation::IStringable* raw = ...
IStringable projected(raw, take_ownership_from_abi);
printf("%ls\n", projected.ToString().c_str());
Génération de code optimisée pour la gestion des exceptions
Cette modification complète le travail effectué par l’équipe de l’optimiseur C++ Microsoft pour réduire le coût de la gestion des exceptions. Si vous utilisez des interfaces binaires d’application (ABIs) (telles que COM) fortement dans votre code, vous observerez un grand nombre de code suivant ce modèle.
int32_t Function() noexcept
{
try
{
// code here constitutes unique value.
}
catch (...)
{
// code here is always duplicated.
}
}
C++/WinRT lui-même génère ce modèle pour chaque API implémentée. Avec des milliers de fonctions d’API, toute optimisation ici peut être significative. Par le passé, l’optimiseur ne détectait pas que ces blocs `catch` étaient tous identiques, si bien qu’il dupliquait beaucoup de code pour chaque ABI, ce qui a à son tour contribué à la croyance selon laquelle l’utilisation des exceptions dans le code système produit des binaires volumineux. Toutefois, à partir de Visual Studio 2019, le compilateur C++ plie toutes ces fonclets catch, et stocke uniquement ceux qui sont uniques. Le résultat est une réduction supplémentaire et globale de 18% la taille du code pour les fichiers binaires qui s’appuient fortement sur ce modèle. Non seulement le code EH est maintenant plus efficace que l’utilisation de codes de retour, mais aussi la préoccupation concernant les fichiers binaires plus volumineux est maintenant une chose du passé.
Améliorations de la compilation incrémentielle
L’outil cppwinrt.exe compare maintenant la sortie d’un fichier d’en-tête/source généré par rapport au contenu d’un fichier existant sur le disque, et il écrit uniquement le fichier si le fichier a en fait changé. Cela permet de gagner beaucoup de temps avec les E/S de disque et garantit que les fichiers ne sont pas considérés comme étant « sales » par le compilateur C++. Le résultat est que la recompilation est évitée ou réduite, dans de nombreux cas.
Les interfaces génériques sont désormais toutes générées
En raison du lecteur de métadonnées xlang, C++/WinRT génère désormais toutes les interfaces paramétrables ou génériques à partir de métadonnées. Les interfaces telles que Windows ::Foundation ::Collections ::IVector<T> sont désormais générées à partir de métadonnées plutôt qu’écrites manuellementwinrt/base.h. Le résultat est que la taille de winrt/base.h a été divisée par deux, et que les optimisations sont générées directement dans le code (ce qui était difficile à faire avec une approche artisanale).
Important
Les interfaces telles que l’exemple donné apparaissent désormais dans leurs en-têtes d’espace de noms respectifs, plutôt que dans winrt/base.h. Par conséquent, si vous ne l’avez pas déjà fait, vous devez inclure l’en-tête d’espace de noms approprié pour utiliser l’interface.
Optimisations des composants
Cette mise à jour ajoute la prise en charge de plusieurs optimisations d’opt-in supplémentaires pour C++/WinRT, décrites dans les sections ci-dessous. Comme ces optimisations constituent des modifications incompatibles (dont la prise en charge peut nécessiter de votre part des ajustements mineurs), vous devrez les activer explicitement. Dans Visual Studio, définissez la propriété de projet Propriétés> communesC++/WinRT>optimisée surOui. Cela a pour effet d’ajouter <CppWinRTOptimized>true</CppWinRTOptimized> à votre fichier de projet. Et cela a le même effet que d’ajouter l’option -opt[imize] lors de l’invocation de cppwinrt.exe à partir de la ligne de commande.
Un nouveau projet (à partir d’un modèle de projet) utilisera -opt par défaut.
Construction uniforme et accès direct à l’implémentation
Ces deux optimisations permettent à votre composant d’accéder directement à ses propres types d’implémentation, même s’il utilise uniquement les types projetés. Il n’est pas nécessaire d’utiliser make, make_self ni get_self si vous souhaitez simplement utiliser l’API publique. Vos appels seront compilés en appels directs vers l’implémentation, et ces appels pourront même être entièrement intégrés en ligne.
Pour plus d’informations et des exemples de code, consultez Activer la construction uniforme et l’accès direct à l’implémentation.
Fabriques effacées de type
Cette optimisation évite les dépendances #include dans module.g.cpp, de sorte qu’il n’ait pas besoin d’être recompilé chaque fois qu’une classe d’implémentation quelconque est modifiée. Le résultat est une amélioration des performances de compilation.
Plus intelligent et plus efficace module.g.cpp pour les grands projets avec plusieurs bibliothèques
Le fichier module.g.cpp contient désormais aussi deux assistants composables supplémentaires, nommés winrt_can_unload_now et winrt_get_activation_factory. Celles-ci ont été conçues pour des projets plus volumineux où une DLL est composée d’un certain nombre de libs, chacune avec ses propres classes runtime. Dans ce cas, vous devez lier manuellement ensemble les fonctions de la DLL DllGetActivationFactory et DllCanUnloadNow. Ces outils vous permettent de le faire beaucoup plus facilement, en évitant les fausses erreurs de création. L’indicateur -lib de l’outil cppwinrt.exe peut également être utilisé pour attribuer à chaque lib son propre préambule (au lieu de winrt_xxx), afin que les fonctions de chaque lib puissent être nommées individuellement et donc combinées sans ambiguïté.
Prise en charge de Coroutine
La prise en charge des coroutines est automatiquement incluse. Auparavant, l’assistance se trouvait à plusieurs endroits, ce qui nous a semblé trop contraignant. Puis temporairement pour la version 2.0, un fichier d’en-tête winrt/coroutine.h a été nécessaire, mais cela n’est plus nécessaire. Étant donné que les interfaces asynchrones Windows Runtime sont désormais générées, plutôt que écrites manuellement, elles résident désormais dans winrt/Windows.Foundation.h. Outre le fait d’être plus facile à maintenir et à prendre en charge, cela signifie que les fonctions utilitaires de coroutine telles que resume_foreground n’ont plus besoin d’être ajoutées à la fin du fichier d’en-tête d’un espace de noms spécifique. Au lieu de cela, ils peuvent inclure plus naturellement leurs dépendances. Cela permet également à resume_foreground de prendre en charge non seulement la reprise de l’exécution sur un Windows::UI::Core::CoreDispatcher donné, mais aussi désormais la reprise de l’exécution sur un Windows::System::DispatcherQueue donné. Auparavant, un seul pouvait être pris en charge ; mais pas les deux, étant donné que la définition ne pouvait résider que dans un espace de noms.
Voici un exemple de la prise en charge de DispatcherQueue.
...
#include <winrt/Windows.System.h>
using namespace Windows::System;
...
fire_and_forget Async(DispatcherQueueController controller)
{
bool queued = co_await resume_foreground(controller.DispatcherQueue());
assert(queued);
// This is just to simulate queue failure...
co_await controller.ShutdownQueueAsync();
queued = co_await resume_foreground(controller.DispatcherQueue());
assert(!queued);
}
Les aides coroutine sont maintenant également décorées avec [[nodiscard]], améliorant ainsi leur facilité d’utilisation. Si vous oubliez de co_await (ou ne vous rendez pas compte que vous devez le faire) pour qu’ils fonctionnent, alors, en raison de [[nodiscard]], ce type d’erreur génère désormais un avertissement du compilateur.
Aide sur le diagnostic des allocations directes (pile)
Étant donné que les noms des classes projetées et d’implémentation sont identiques par défaut et ne diffèrent que par leur espace de noms, il est possible de les confondre et de créer accidentellement une implémentation dans la pile, au lieu d’utiliser la famille de fonctions utilitaires make. Cela peut être difficile à diagnostiquer dans certains cas, car l’objet peut être détruit alors que les références en suspens sont toujours en vol. Une assertion prend désormais cela en compte dans les versions de débogage. Bien que l’assertion ne détecte pas l’allocation de pile à l’intérieur d’une coroutine, il est néanmoins utile d’intercepter la plupart de ces erreurs.
Pour plus d’informations, consultez Diagnostic des allocations directes.
Amélioration des assistances de capture et des délégués variadiques
Cette mise à jour corrige la limitation liée aux assistants de capture en prenant désormais aussi en charge les types projetés. Cela se produit de temps en temps avec les API d’interopérabilité Windows Runtime, lorsqu’elles renvoient un type projeté.
Cette mise à jour ajoute également la prise en charge de get_strong et de get_weak lors de la création d’un délégué variadique (non-Windows Runtime).
Prise en charge de la destruction différée et du QI sûr pendant la destruction
Il n’est pas rare que, dans le destructeur d’un objet de classe d’exécution, on appelle une méthode qui incrémente temporairement le compteur de références. Lorsque le nombre de références retourne à zéro, l’objet détruit une seconde fois. Dans une application XAML, vous devrez peut-être effectuer un QueryInterface (QI) dans un destructeur, afin d’appeler une implémentation de nettoyage vers le haut ou vers le bas de la hiérarchie. Mais le nombre de références de l’objet a déjà atteint zéro, de sorte que QI constitue également un rebond de nombre de références.
Cette mise à jour ajoute la prise en charge de l’anti-rebond du compteur de références, garantissant qu’une fois celui-ci tombé à zéro, il ne peut plus être réactivé, tout en vous permettant toujours d’effectuer un QI sur tout objet temporaire nécessaire pendant la destruction. Cette procédure est inévitable dans certaines applications/contrôles XAML, et C++/WinRT est désormais résiliente.
Vous pouvez différer la destruction en fournissant une fonction de final_release statique sur votre type d’implémentation. Le dernier pointeur restant vers l’objet, sous la forme d’un std ::unique_ptr, est passé à votre final_release. Vous pouvez ensuite choisir de déplacer la propriété de ce pointeur vers un autre contexte. Vous pouvez QI le pointeur en toute sécurité sans provoquer une double destruction. Toutefois, la modification nette du nombre de références doit être égale à zéro au moment où vous destructeurz l’objet.
La valeur de retour de final_release peut être void, un objet d’opération asynchrone tel que IAsyncAction ou winrt ::fire_and_forget.
struct Sample : implements<Sample, IStringable>
{
hstring ToString()
{
return L"Sample";
}
~Sample()
{
// Called when the unique_ptr below is reset.
}
static void final_release(std::unique_ptr<Sample> self) noexcept
{
// Move 'self' as needed to delay destruction.
}
};
Dans l’exemple ci-dessous, une fois la mainPage publiée (pour la dernière fois), final_release est appelée. Cette fonction attend cinq secondes (dans le pool de threads), puis reprend son exécution en utilisant le Dispatcher de la page (ce qui nécessite QI/AddRef/Release pour fonctionner). Il nettoie ensuite une ressource sur ce thread d’interface utilisateur. Enfin, il efface le unique_ptr, ce qui provoque l’appel du destructeur MainPage . Même dans ce destructeur, DataContext est appelé, ce qui nécessite un QI pour IFrameworkElement.
Vous n’avez pas besoin d’implémenter votre final_release en tant que coroutine. Mais cela fonctionne, et il est très simple de déplacer la destruction vers un autre thread, ce qui se passe dans cet exemple.
struct MainPage : PageT<MainPage>
{
MainPage()
{
}
~MainPage()
{
DataContext(nullptr);
}
static IAsyncAction final_release(std::unique_ptr<MainPage> self)
{
co_await 5s;
co_await resume_foreground(self->Dispatcher());
co_await self->resource.CloseAsync();
// The object is destructed normally at the end of final_release,
// when the std::unique_ptr<MyClass> destructs. If you want to destruct
// the object earlier than that, then you can set *self* to `nullptr`.
self = nullptr;
}
};
Pour plus d’informations, consultez Destruction différée.
Prise en charge améliorée de l’héritage d’interface unique de style COM
Ainsi que pour la programmation Windows Runtime, C++/WinRT est également utilisé pour créer et consommer des API COM uniquement. Cette mise à jour permet d’implémenter un serveur COM où il existe une hiérarchie d’interface. Cela n'est pas nécessaire pour le Windows Runtime ; mais il est nécessaire pour certaines implémentations COM.
Gestion correcte des out params
Il peut être délicat de travailler avec les paramètres out ; en particulier les tableaux Windows Runtime. Avec cette mise à jour, C++/WinRT est nettement plus robuste et plus résistant aux erreurs en ce qui concerne les paramètres out et les tableaux, que ces paramètres proviennent d’une projection de langage ou d’un développeur COM utilisant l’ABI brute et commettant l’erreur de ne pas initialiser les variables de manière cohérente. Dans les deux cas, C++/WinRT fait désormais ce qu’il faut lorsqu’il s’agit de transmettre des types projetés à l’ABI (en veillant à libérer toutes les ressources), et lorsqu’il s’agit de mettre à zéro ou de réinitialiser les paramètres transmis via l’ABI.
Les événements gèrent désormais les jetons non valides de manière fiable
L’implémentation winrt ::event gère désormais correctement le cas où sa méthode remove est appelée avec une valeur de jeton non valide (valeur qui n’est pas présente dans le tableau).
Les variables locales coroutine sont maintenant détruites avant que la coroutine ne retourne
La méthode traditionnelle d’implémentation d’un type de coroutine peut permettre que les variables locales de la coroutine soient détruites après que la coroutine se termine/achève son exécution (plutôt qu’avant la suspension finale). La reprise de tout processus en attente est désormais différée jusqu’à la suspension définitive, afin d’éviter ce problème et d’obtenir d’autres avantages.
Actualités et modifications, dans Windows SDK version 10.0.17763.0 (Windows 10, version 1809)
Le tableau ci-dessous contient des actualités et des modifications pour C++/WinRT dans le kit sdk Windows version 10.0.17763.0 (Windows 10, version 1809).
| Fonctionnalité nouvelle ou modifiée | Plus d’informations |
|---|---|
| Changement cassant. Pour qu'il soit compilé, C++/WinRT ne dépend pas des en-têtes du SDK Windows. | Consultez Isolation vis-à-vis des fichiers d’en-tête du SDK Windows, ci-dessous. |
| Le format du système de projet Visual Studio a changé. | Découvrez comment recibler votre projet C++/WinRT vers une version ultérieure du SDK Windows, ci-dessous. |
| Il existe de nouvelles fonctions et classes de base pour vous aider à transmettre un objet de collection à une fonction Windows Runtime, ou à implémenter vos propres propriétés de collection et types de collection. | Consultez Collections avec C++/WinRT. |
| Vous pouvez utiliser l’extension de balisage {Binding} avec vos classes runtime C++/WinRT. | Pour plus d’informations et pour obtenir des exemples de code, consultez la vue d’ensemble de la liaison de données. |
| La possibilité d’annuler une coroutine vous permet d’enregistrer un rappel d’annulation. | Pour plus d’informations et des exemples de code, consultez Annulation d’une opération asynchrone et rappels d’annulation. |
| Lors de la création d’un délégué qui pointe vers une fonction membre, vous pouvez établir une référence forte ou faible à l’objet courant (au lieu d’un pointeur brut this) lors de l’enregistrement du gestionnaire. | Pour plus d’informations et des exemples de code, consultez la sous-section Si vous utilisez une fonction membre comme délégué de la section Accéder en toute sécurité au pointeur this avec un délégué de gestion des événements. |
| Les bogues sont corrigés qui ont été découverts par la conformité améliorée de Visual Studio à la norme C++. La chaîne d’outils LLVM et Clang est également mieux exploitée pour valider la conformité aux normes de C++/WinRT. | Vous ne rencontrerez plus le problème décrit dans Pourquoi mon nouveau projet ne sera-t-il pas compilé ? J'utilise Visual Studio 2017 (version 15.8.0 ou ultérieure) et sdk version 17134 |
Autres modifications.
-
Rupture de compatibilité.
winrt ::get_abi(winrt ::hstring const&) retourne
void*désormais au lieu deHSTRING. Vous pouvez utiliserstatic_cast<HSTRING>(get_abi(my_hstring));pour obtenir un HSTRING. Consultez l’interopérabilité avec le HSTRING d’ABI. -
Changement cassant.
winrt::put_abi(winrt::hstring&) renvoie désormais
void**au lieu deHSTRING*. Vous pouvez utiliserreinterpret_cast<HSTRING*>(put_abi(my_hstring));pour obtenir un HSTRING*. Consultez l’interopérabilité avec le HSTRING d’ABI. -
Changement cassant. HRESULT est maintenant projeté en tant que winrt ::hresult. Si vous avez besoin d’un HRESULT (pour effectuer la vérification de type ou pour prendre en charge les caractéristiques de type), vous pouvez
static_castobtenir un winrt ::hresult. Sinon, winrt ::hresult se convertit en HRESULT, tant que vous incluezunknwn.havant d’inclure les en-têtes C++/WinRT. -
Changement cassant. GUID est maintenant projeté en tant que winrt ::guid. Pour les API que vous implémentez, vous devez utiliser winrt ::guid pour les paramètres GUID. Sinon, winrt ::guid se convertit en GUID, tant que vous incluez
unknwn.havant d’inclure des en-têtes C++/WinRT. Consultez l’interopérabilité avec la structure GUID de l’ABI. - Changement cassant. Le constructeur winrt ::handle_type a été renforcé en le rendant explicite (il est désormais plus difficile d’écrire du code incorrect avec celui-ci). Si vous devez affecter une valeur de handle brute, appelez la fonction handle_type ::attach à la place.
-
Changement majeur. Les signatures de WINRT_CanUnloadNow et de WINRT_GetActivationFactory ont changé. Vous ne devez pas déclarer ces fonctions du tout. Au lieu de cela, incluez
winrt/base.h(qui est automatiquement inclus si vous incluez des fichiers d’en-tête d’espace de noms C++/WinRT Windows) pour inclure les déclarations de ces fonctions. - Pour la struct winrt::clock, from_FILETIME/to_FILETIME sont obsolètes au profit de from_file_time/to_file_time.
- API simplifiées qui attendent des paramètres IBuffer . La plupart des API préfèrent les regroupements ou les tableaux. Mais nous avons estimé que nous devrions faciliter l’appel d’API qui reposent sur IBuffer. Cette mise à jour fournit un accès direct aux données derrière une implémentation IBuffer . Il utilise la même convention d’affectation de noms de données que celle utilisée par les conteneurs de bibliothèque standard C++. Cette convention évite également les collisions avec les noms de métadonnées qui commencent conventionnellement par une lettre majuscule.
- Génération de code améliorée : diverses améliorations visant à réduire la taille du code, à améliorer l’inlining et à optimiser la mise en cache des fabriques.
- Suppression d’une récursivité inutile. Lorsque la ligne de commande fait référence à un dossier, plutôt qu’à un dossier spécifique
.winmd, l’outilcppwinrt.exene recherche plus de fichiers de manière.winmdrécursive. L’outilcppwinrt.exegère également les doublons de manière plus intelligente, ce qui le rend plus résilient aux erreurs utilisateur et aux fichiers mal formés.winmd. - Pointeurs intelligents renforcés. Auparavant, les révoqueurs d’événements n’ont pas pu révoquer lors de l’affectation d’une nouvelle valeur au déplacement. Cela a permis de mettre au jour un problème où les classes de pointeurs intelligents ne géraient pas correctement et de manière fiable l’auto-affectation, dont l’origine se trouvait dans le winrt::com_ptr struct template. winrt::com_ptr a été corrigé, et les révocateurs d’événements ont été corrigés pour gérer correctement la sémantique de déplacement, de sorte qu’ils se révoquent lors d’une affectation.
Important
Des modifications importantes ont été apportées à l’extension de Visual Studio C++/WinRT (VSIX), à la fois dans la version 1.0.181002.2, puis ultérieurement dans la version 1.0.190128.4. Pour en savoir plus sur ces modifications et leur incidence sur vos projets existants, prise en charge de C++/WinRT dans Visual Studio et les versions antérieures de l’extension VSIX.
Isolation des fichiers d’en-tête du SDK Windows
Il s’agit potentiellement d’une modification cassant pour votre code.
Pour qu’il soit compilé, C++/WinRT ne dépend plus des fichiers d’en-tête à partir du SDK Windows. Les fichiers d'en-tête de la bibliothèque d'exécution C (CRT) et de la bibliothèque de modèles standard C++ (STL) n'incluent pas non plus d'en-têtes de SDK Windows. Et qui améliore la conformité aux normes, évite les dépendances accidentelles et réduit considérablement le nombre de macros que vous devez protéger.
Cette indépendance signifie que C++/WinRT est désormais plus portable et conforme aux normes, et qu’il augmente la possibilité de devenir une bibliothèque inter-compilateur et multiplateforme. Cela signifie également que les en-têtes C++/WinRT ne subissent pas les effets négatifs des macros.
Si vous comptiez auparavant sur C++/WinRT pour inclure les fichiers d’en-tête Windows dans votre projet, vous devrez désormais les inclure vous-même. Dans tous les cas, il est toujours recommandé d’inclure explicitement les en-têtes dont vous dépendez, et de ne pas les laisser à une autre bibliothèque pour les inclure pour vous.
Actuellement, les seules exceptions à l’isolation des fichiers d’en-tête du SDK Windows concernent les intrinsèques et les types numériques. Il n’existe aucun problème connu avec ces dernières dépendances restantes.
Dans votre projet, vous pouvez réactiver l’interopérabilité avec les en-têtes du SDK Windows si nécessaire. Vous pouvez, par exemple, implémenter une interface COM (rootée dans IUnknown). Pour cet exemple, incluez unknwn.h avant d’inclure tous les en-têtes C++/WinRT. Cela amène la bibliothèque de base C++/WinRT à activer divers hooks afin de prendre en charge les interfaces COM classiques. Pour obtenir un exemple de code, consultez Créer des composants COM avec C++/WinRT. De même, incluez explicitement les autres en-têtes du KIT de développement logiciel (SDK) Windows qui déclarent des types et/ou des fonctions que vous souhaitez appeler.
Comment recibler votre projet C++/WinRT vers une version ultérieure du SDK Windows
La méthode de reciblage de votre projet susceptible d’entraîner le plus petit problème de compilateur et d’éditeur de liens est également la plus gourmande en main-d’œuvre. Cette méthode implique la création d’un projet (ciblant la version Windows SDK de votre choix), puis la copie de fichiers vers votre nouveau projet à partir de votre ancien projet. Certaines sections de vos anciens fichiers .vcxproj et .vcxproj.filters que vous pourrez simplement recopier vous éviteront d’avoir à ajouter des fichiers dans Visual Studio.
Toutefois, il existe deux autres façons de recibler votre projet dans Visual Studio.
- Accédez à la propriété de projet General>Windows SDK Version, puis sélectionnez Toutes les configurations et toutes les plateformes. Définissez Version du SDK Windows sur la version que vous souhaitez cibler.
- Dans Explorateur de solutions, cliquez avec le bouton droit sur le nœud du projet, cliquez sur Retarget Projects, choisissez la ou les versions que vous souhaitez cibler, puis cliquez sur OK.
Si vous rencontrez des erreurs de compilateur ou d’éditeur de liens après avoir utilisé l’une de ces deux méthodes, vous pouvez essayer de nettoyer la solution (Générer> unesolution propre et/ou supprimer manuellement tous les dossiers et fichiers temporaires) avant de réessayer de générer.
Si le compilateur C++ génère l'« erreur C2039 : « IUnknown » : n’est pas membre de « l’espace de noms global », puis ajoutez-y #include <unknwn.h> en haut de votre pch.h fichier (avant d’inclure des en-têtes C++/WinRT).
Vous devrez peut-être également ajouter #include <hstring.h> après cela.
Si l’éditeur de liens C++ génère « erreur LNK2019 : symbole externe non résolu _WINRT_CanUnloadNow@0 référencé dans la fonction _VSDesignerCanUnloadNow@0 », vous pouvez le résoudre en ajoutant #define _VSDESIGNER_DONT_LOAD_AS_DLL à votre pch.h fichier.
Windows developer