Types de données C++ standard et C++/WinRT
Avec C++/WinRT, vous pouvez appeler des API Windows Runtime à l’aide de types de données C++ standard, y compris certains types de données de la bibliothèque C++ standard. Vous pouvez passer des chaînes standard aux API (consultez Gestion des chaînes en C++/WinRT), et passer des listes d’initialiseurs et des conteneurs standard aux API qui attendent une collection sémantiquement équivalente.
Consultez également Passage de paramètres à la frontière ABI.
Listes d’initialiseurs standard
Une liste d’initialiseurs (std::initializer_list) est une construction de la bibliothèque C++ standard. Vous pouvez utiliser des listes d’initialiseurs lorsque vous appelez certains constructeurs et méthodes Windows Runtime. Par exemple, vous pouvez appeler DataWriter::WriteBytes avec une telle liste.
#include <winrt/Windows.Storage.Streams.h>
using namespace winrt::Windows::Storage::Streams;
int main()
{
winrt::init_apartment();
InMemoryRandomAccessStream stream;
DataWriter dataWriter{stream};
dataWriter.WriteBytes({ 99, 98, 97 }); // the initializer list is converted to a winrt::array_view before being passed to WriteBytes.
}
Il existe deux éléments impliqués dans cette tâche. Tout d’abord, la méthode DataWriter::WriteBytes prend un paramètre de type winrt::array_view.
void WriteBytes(winrt::array_view<uint8_t const> value) const
winrt::array_view est un type personnalisé C++/WinRT qui représente en toute sécurité une série contiguë de valeurs (définie dans la bibliothèque de base C++/WinRT, à savoir %WindowsSdkDir%Include\<WindowsTargetPlatformVersion>\cppwinrt\winrt\base.h
).
Deuxièmement, winrt::array_view possède un constructeur initialiseur-liste.
template <typename T> winrt::array_view(std::initializer_list<T> value) noexcept
Dans de nombreux cas, vous pouvez choisir ou non de prendre en compte winrt::array_view dans votre programmation. Si vous choisissez de ne pas le prendre en compte, vous ne devrez changer aucun code si un type équivalent s’affiche dans la bibliothèque C++ standard.
Vous pouvez transmettre une liste d’initialiseurs à une API Windows Runtime qui attend un paramètre de collection. Prenons StorageItemContentProperties::RetrievePropertiesAsync comme exemple.
IAsyncOperation<IMap<winrt::hstring, IInspectable>> StorageItemContentProperties::RetrievePropertiesAsync(IIterable<winrt::hstring> propertiesToRetrieve) const;
Vous pouvez appeler cette API avec une liste d’initialiseurs comme suit.
IAsyncAction retrieve_properties_async(StorageFile const storageFile)
{
auto properties{ co_await storageFile.Properties().RetrievePropertiesAsync({ L"System.ItemUrl" }) };
}
Deux facteurs sont impliqués ici. Tout d’abord, l’appelé construit un std::vector à partir de la liste d’initialiseurs (cet appelé est asynchrone, donc il peut être - et doit être - le propriétaire de cet objet). Deuxièmement, C++/WinRT lie de manière transparente (et sans créer de copies) std::vector comme un paramètre de collection Windows Runtime.
Vecteurs et tableaux standard
winrt::array_view a également des constructeurs de conversion à partir de std::vector et std::array.
template <typename C, size_type N> winrt::array_view(std::array<C, N>& value) noexcept
template <typename C> winrt::array_view(std::vector<C>& vectorValue) noexcept
Par conséquent, vous pouvez appeler à la place DataWriter::WriteBytes avec un std::vector.
std::vector<byte> theVector{ 99, 98, 97 };
dataWriter.WriteBytes(theVector); // theVector is converted to a winrt::array_view before being passed to WriteBytes.
Ou avec un std::array.
std::array<byte, 3> theArray{ 99, 98, 97 };
dataWriter.WriteBytes(theArray); // theArray is converted to a winrt::array_view before being passed to WriteBytes.
C++/WinRT lie std::vector comme un paramètre de collection Windows Runtime. Par conséquent, vous pouvez transmettre un std::vector<winrt::hstring>, et il sera converti dans la collection Windows Runtime appropriée de winrt::hstring. Il existe des informations supplémentaires à prendre en compte si l’appelé est asynchrone. En raison des détails d’implémentation de ce cas, vous devez fournir un rvalue et donc une copie ou un déplacement du vecteur. Dans l’exemple de code ci-dessous, nous passons la propriété du vecteur à l’objet du type de paramètre accepté par l’appelé asynchrone (en veillant à ne pas accéder à nouveau à vecH
après l’avoir déplacé). Pour en savoir plus sur rvalues, consultez Catégories de valeurs et références.
IAsyncAction retrieve_properties_async(StorageFile const storageFile, std::vector<winrt::hstring> vecH)
{
auto properties{ co_await storageFile.Properties().RetrievePropertiesAsync(std::move(vecH)) };
}
Mais vous ne pouvez pas transmettre un std::vector<std::wstring> là où une collection Windows Runtime est attendue. Cela est dû au fait que, la collection Windows Runtime appropriée de std::wstring ayant été convertie, le langage C++ ne forcera pas le ou les paramètres de type de cette collection. Par conséquent, l’exemple de code suivant ne sera pas compilé (et la solution consiste à passer un std::vector<winrt::hstring> à la place, comme indiqué ci-dessus).
IAsyncAction retrieve_properties_async(StorageFile const storageFile, std::vector<std::wstring> vecW)
{
auto properties{ co_await storageFile.Properties().RetrievePropertiesAsync(std::move(vecW)) }; // error! Can't convert from vector of wstring to async_iterable of hstring.
}
Tableaux bruts et plages de pointeurs
En gardant en tête qu’un type équivalent peut exister dans l’avenir dans la bibliothèque C++ standard, vous pouvez également travailler directement avec winrt::array_view, par choix ou par nécessité.
winrt::array_view a des constructeurs de conversion à partir d’un tableau brut et d’une plage de T* (pointeurs vers le type d’élément).
using namespace winrt;
...
byte theRawArray[]{ 99, 98, 97 };
array_view<byte const> fromRawArray{ theRawArray };
dataWriter.WriteBytes(fromRawArray); // the winrt::array_view is passed to WriteBytes.
array_view<byte const> fromRange{ theArray.data(), theArray.data() + 2 }; // just the first two elements.
dataWriter.WriteBytes(fromRange); // the winrt::array_view is passed to WriteBytes.
Opérateurs et fonctions winrt::array_view
Une série de constructeurs, d’opérateurs, de fonctions et d’itérateurs sont implémentés pour winrt::array_view. Un winrt::array_view étant une plage, vous pouvez l’utiliser avec for
basé sur les plages ou avec std::for_each.
Pour plus d’exemples et d’informations, consultez la rubrique sur les informations de référence sur les API winrt::array_view.
IVector<T> et constructions d’itération standard
SyndicationFeed.Items est un exemple d’API Windows Runtime qui retourne une collection de type IVector<T> (projeté dans C++/WinRT comme winrt::Windows::Foundation::Collections::IVector<T>). Vous pouvez utiliser ce type avec des constructions d’itération standard, par exemple des for
basés sur les plages.
// main.cpp
#include "pch.h"
#include <winrt/Windows.Web.Syndication.h>
#include <iostream>
using namespace winrt;
using namespace Windows::Web::Syndication;
void PrintFeed(SyndicationFeed const& syndicationFeed)
{
for (SyndicationItem const& syndicationItem : syndicationFeed.Items())
{
std::wcout << syndicationItem.Title().Text().c_str() << std::endl;
}
}
Coroutines C++ avec des API Windows Runtime asynchrones
Vous pouvez continuer à utiliser la Bibliothèque de modèles parallèles (PPL) lors de l’appel aux API Windows Runtime asynchrones. Toutefois, dans de nombreux cas, les coroutines C++ fournissent un idiome efficace et plus facilement codé pour interagir avec les objets asynchrones. Pour plus d’informations et des exemples de code, voir Opérations concurrentes et asynchrones avec C++/WinRT.