C++-Standarddatentypen und C++/WinRT

Mit C++/WinRT können Sie Windows-Runtime APIs mit Standard-C++-Datentypen aufrufen, einschließlich einiger C++-Standardbibliothek-Datentypen. Sie können Standardzeichenfolgen an APIs übergeben (siehe Zeichenfolgenbehandlung in C++/WinRT), und Sie können Initialisierungslisten und Standardcontainer an APIs übergeben, die eine semantisch gleichwertige Auflistung erwarten.

Siehe auch Parameter über die ABI-Grenze übergeben.

Standard-Initialisierungslisten

Eine Initialisierungsliste (std::initializer_list) ist ein C++-Standardbibliothekskonstrukt. Sie können Initialisierungslisten verwenden, wenn Sie bestimmte Windows-Runtime Konstruktoren und Methoden aufrufen. Sie können z. B. DataWriter::WriteBytes mit einem aufrufen.

#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.
}

Damit das funktioniert, sind zwei Komponenten erforderlich. Zunächst verwendet die DataWriter::WriteBytes-Methode einen Parameter vom Typ "winrt::array_view".

void WriteBytes(winrt::array_view<uint8_t const> value) const

winrt::array_view ist ein benutzerdefinierter C++/WinRT-Typ, der sicher eine zusammenhängende Reihe von Werten darstellt (sie wird in der C++/WinRT-Basisbibliothek definiert, was heißt %WindowsSdkDir%Include\<WindowsTargetPlatformVersion>\cppwinrt\winrt\base.h).

Zweitens verfügt winrt::array_view über einen Initialisierungslistenkonstruktor.

template <typename T> winrt::array_view(std::initializer_list<T> value) noexcept

In vielen Fällen können Sie auswählen, ob Sie winrt::array_view in Ihrer Programmierung beachten möchten. Wenn Sie dies nicht beachten möchten, haben Sie keinen Code, um zu ändern, ob und wann ein entsprechender Typ in der C++-Standardbibliothek angezeigt wird.

Sie können eine Initialisierungsliste an eine Windows-Runtime-API übergeben, die einen Sammlungsparameter erwartet. Nehmen Sie StorageItemContentProperties::RetrievePropertiesAsync als Beispiel.

IAsyncOperation<IMap<winrt::hstring, IInspectable>> StorageItemContentProperties::RetrievePropertiesAsync(IIterable<winrt::hstring> propertiesToRetrieve) const;

Sie können diese API mit einer Initialisierungsliste wie diesem aufrufen.

IAsyncAction retrieve_properties_async(StorageFile const storageFile)
{
    auto properties{ co_await storageFile.Properties().RetrievePropertiesAsync({ L"System.ItemUrl" }) };
}

Hier arbeiten zwei Faktoren. Erstens: Der Aufgerufene konstruiert auf der Grundlage der Initialisierungsliste einen Standardvektor (std::vector). (Dieser Aufgerufene ist asynchron und kann daher das Objekt besitzen, was in diesem Fall erforderlich ist.) Zweitens verwendet C++/WinRT std::vector transparent (und ohne Kopien zu erzeugen) als Windows-Runtime-Sammlungsparameter.

Standard-Arrays und Vektoren

winrt::array_view verfügt auch über Konvertierungskonstruktoren aus "std::vector " und "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

Sie können also stattdessen DataWriter::WriteBytes mit einem std::vector aufrufen.

std::vector<byte> theVector{ 99, 98, 97 };
dataWriter.WriteBytes(theVector); // theVector is converted to a winrt::array_view before being passed to WriteBytes.

Oder mit einem 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 bindet std::vector als Windows-Runtime Sammlungsparameter. Du kannst also std::vector<winrt::hstring> übergeben, und es wird in die entsprechende Windows-Runtime-Sammlung winrt::hstring konvertiert. Bei einem asynchronen Aufgerufenen ist noch ein weiteres Detail zu beachten. Die Implementierungsdetails dieses Falls machen die Angabe eines R-Werts (rvalue) erforderlich. Du musst also eine Kopie oder Verschiebung des Vektors angeben. Im folgenden Codebeispiel verschieben wir den Besitz des Vektors in das Objekt des Parametertyps, der vom asynchronen Angerufenen akzeptiert wird (und dann achten wir darauf, nach dem Verschieben nicht erneut darauf zuzugreifen vecH ). Weitere Informationen zu Wertwerten finden Sie unter Wertkategorien und Verweise darauf.

IAsyncAction retrieve_properties_async(StorageFile const storageFile, std::vector<winrt::hstring> vecH)
{
	auto properties{ co_await storageFile.Properties().RetrievePropertiesAsync(std::move(vecH)) };
}

std::vector<std::wstring> kann jedoch nicht übergeben werden, wenn eine Windows-Runtime-Sammlung erwartet wird. Das liegt daran, dass C++ die Typparameter dieser Sammlung nicht erzwingt, nachdem sie in die entsprechende Windows-Runtime-Sammlung std::wstring konvertiert wurde. Folglich wird das folgende Codebeispiel nicht kompiliert (und die Lösung besteht darin, stattdessen eine std::vector<winrt::hstring> zu übergeben, wie oben gezeigt).

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.
}

Raw-Arrays und Zeigerbereiche

Bedenken Sie, dass in zukunft in der C++-Standardbibliothek ein gleichwertiger Typ vorhanden sein kann, können Sie auch direkt mit winrt::array_view arbeiten, wenn Sie sich dafür entscheiden oder müssen.

winrt::array_view verfügt über Konvertierungskonstruktoren für ein unformatiertes Array sowie für einen Bereich von T* (Zeiger auf den Elementtyp).

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.

winrt::array_view Funktionen und Operatoren

Für winrt::array_view werden eine Vielzahl von Konstruktoren, Operatoren, Funktionen und Iteratoren implementiert. Da es sich bei winrt::array_view sich um einen Bereich handelt, kann das Element mit for (bereichsbasiert) oder mit std::for_each verwendet werden.

Weitere Beispiele und Informationen finden Sie im Referenzthema "winrt::array_view-API ".

IVector<T> und Standard-Iterationskonstrukte

SyndicationFeed.Items ist ein Beispiel für eine Windows-Runtime-API, die eine Auflistung vom Typ IVector<T> zurückgibt (projiziert in C++/WinRT als winrt::Windows::Foundation::Collections::IVector<T>). Dieser Typ kann mit Standarditerationskonstrukten wie for (bereichsbasiert) verwendet werden.

// 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;
    }
}

C++-Coroutines mit asynchronen Windows-Runtime-APIs

Sie können die Parallel Patterns Library (PPL) weiterhin verwenden, wenn Sie asynchrone Windows-Runtime-APIs aufrufen. In vielen Fällen bieten C++-Coroutinen jedoch ein effizientes und einfacher codiertes Idiom für die Interaktion mit asynchronen Objekten. Weitere Informationen und Codebeispiele finden Sie unter Parallelität und asynchrone Vorgänge mit C++/WinRT.

Wichtige APIs