Tipos de dados C++ padrão e C++/WinRT

Com C++/WinRT, você pode chamar APIs do Windows Runtime usando tipos de dados padrão do C++, incluindo alguns tipos de dados da Biblioteca Padrão do C++. Você pode passar cadeias de caracteres padrão para APIs (consulte Tratamento de cadeia de caracteres em C++/WinRT) e pode passar listas de inicializadores e contêineres padrão para APIs que esperam uma coleção semanticamente equivalente.

Veja também Passando parâmetros pela fronteira da ABI.

Listas de inicializadores padrão

Uma lista de inicializadores (std::initializer_list) é um constructo da Biblioteca Padrão C++. Você pode usar listas de inicializadores ao chamar determinados construtores e métodos Windows Runtime. Por exemplo, você pode chamar DataWriter::WriteBytes com um.

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

Há duas partes envolvidas em fazer isso funcionar. Primeiro, o método DataWriter::WriteBytes usa um parâmetro do tipo winrt::array_view.

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

winrt::array_view é um tipo C++/WinRT personalizado que representa com segurança uma série contígua de valores (ele é definido na biblioteca base C++/WinRT, que é %WindowsSdkDir%Include\<WindowsTargetPlatformVersion>\cppwinrt\winrt\base.h).

Em segundo lugar, winrt::array_view tem um construtor de lista de inicializadores.

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

Em muitos casos, você pode escolher se deseja ou não estar ciente de winrt::array_view em sua programação. Se você optar por não estar ciente disso, não terá nenhum código para alterar se e quando um tipo equivalente aparecer na Biblioteca Padrão C++.

Você pode passar uma lista de inicialização para uma API do Windows Runtime que espera um parâmetro de coleção. Considere StorageItemContentProperties::RetrievePropertiesAsync, por exemplo.

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

Você pode chamar essa API com uma lista de inicializadores como esta.

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

Dois fatores estão funcionando aqui. Primeiro, o computador chamado constrói um std::vector a partir da lista de inicializadores (esse computador chamado é assíncrono, portanto, pode ser proprietário desse objeto, e deve ser). Segundo, o C++/WinRT associa std:: Vector de forma transparente (e sem introduzir cópias) como um parâmetro de coleção do Windows Runtime.

Matrizes e vetores padrão

winrt::array_view também tem construtores de conversão de std::vector e 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

Portanto, você pode chamar DataWriter::WriteBytes com um 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 com um 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 associa std::vector como um parâmetro de coleção Windows Runtime. Assim, é possível passar um std::vector<winrt::hstring>, e ele é convertido na coleção apropriada do Windows Runtime de winrt::hstring. Há um detalhe adicional a considerar se o computador chamado for assíncrono. Devido aos detalhes de implementação nesse caso, é preciso fornecer um rvalue, portanto é necessário fornecer uma cópia ou um movimento do vetor. No exemplo de código abaixo, movemos a propriedade do vetor para o objeto do tipo de parâmetro aceito pelo chamador assíncrono (e, em seguida, temos o cuidado de não acessar vecH novamente depois de movê-lo). Se você quiser saber mais sobre rvalues, consulte categorias de valor e referências a elas.

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

Entretanto, não é possível passar um std::vector<std::wstring> quando se espera uma coleção do Windows Runtime. Isso acontece porque, ao converter para a coleção apropriada do Windows Runtime de std::wstring, a linguagem C++ não forçará os parâmetros de tipo dessa coleção. Consequentemente, o exemplo de código a seguir não será compilado (e a solução é passar um std::vector<winrt::hstring> em vez disso, conforme mostrado acima).

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

Matrizes brutas e intervalos de ponteiro

Tendo em mente a ressalva de que um tipo equivalente pode existir no futuro na Biblioteca Padrão C++, você também pode trabalhar diretamente com winrt::array_view se optar por ou precisar.

winrt::array_view tem construtores de conversão de uma matriz bruta e de um intervalo de T* (ponteiros para o tipo de elemento).

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: funções e operadores

Um host de construtores, operadores, funções e iteradores são implementados para winrt::array_view. Um winrt::array_view é um intervalo, então é possível usá-lo com for baseado em intervalo ou com std::for_each.

Para obter mais exemplos e informações, consulte o tópico de referência da API winrt::array_view .

IVector<T> e construções de iteração padrão

SyndicationFeed.Items é um exemplo de uma API Windows Runtime que retorna uma coleção do tipo IVector<T> (projetada em C++/WinRT como winrt::Windows::Foundation::Collections::IVector<T>). Você pode usar esse tipo com construções de iteração padrão, como for baseado em intervalo.

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

Corrotinas C++ com APIs assíncronas do Windows Runtime

Você pode continuar a usar a PPL (Biblioteca de Padrões Paralelos) ao chamar APIs assíncronas Windows Runtime. No entanto, em muitos casos, as coroutinas C++ fornecem um idioma eficiente e mais facilmente codificado para interagir com objetos assíncronos. Para obter mais informações e exemplos de código, consulte Simultaneidade e operações assíncronas com C++/WinRT.

APIs importantes