标准 C++ 数据类型和 C++/WinRTStandard C++ data types and C++/WinRT

借助 C++/WinRT,可以使用标准 C++ 数据类型(包括某些 C++ 标准库数据类型)调用 Windows 运行时 API。With C++/WinRT, you can call Windows Runtime APIs using Standard C++ data types, including some C++ Standard Library data types. 可以将标准字符串传递到 API(请参阅 C++/WinRT 中的字符串处理),还可以将初始值列表和标准容器传递到 API,这些 API 需要语义上等价的集合。You can pass standard strings to APIs (see String handling in C++/WinRT), and you can pass initializer lists and standard containers to APIs that expect a semantically equivalent collection.

另请参阅将参数传递到 ABI 边界Also see Passing parameters into the ABI boundary.

标准初始值列表Standard initializer lists

初始值列表 (std::initializer_list) 是 C++ 标准库构造 。An initializer list (std::initializer_list) is a C++ Standard Library construct. 调用特定的 Windows 运行时构造函数和方法时,可以使用初始值列表。You can use initializer lists when you call certain Windows Runtime constructors and methods. 例如,可以使用初始值列表来调用 DataWriter::WriteBytes For example, you can call DataWriter::WriteBytes with one.

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

此工作分为两个部分。There are two pieces involved in making this work. 第一,DataWriter::WriteBytes 方法选取一个 winrt::array_view 类型的参数 First, the DataWriter::WriteBytes method takes a parameter of type winrt::array_view.

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

winrt::array_view 是用于安全地表示一系列连续值的自定义 C++/WinRT 类型(它在 C++/WinRT 基础库 中定义) %WindowsSdkDir%Include\<WindowsTargetPlatformVersion>\cppwinrt\winrt\base.hwinrt::array_view is a custom C++/WinRT type that safely represents a contiguous series of values (it is defined in the C++/WinRT base library, which is %WindowsSdkDir%Include\<WindowsTargetPlatformVersion>\cppwinrt\winrt\base.h).

第二,winrt::array_view 有一个初始值列表构造函数 。Second, winrt::array_view has an initializer-list constructor.

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

在很多情况下,可以选择是否要注意编程中的 winrt::array_view 。In many cases, you can choose whether or not to be aware of winrt::array_view in your programming. 如果你选择不注意它,那么在等效类型出现在 C++ 标准库中时不用更改任何代码 。If you choose not to be aware of it then you won't have any code to change if and when an equivalent type appears in the C++ Standard Library.

可以将初始值列表传递给需要集合参数的 Windows 运行时 API。You can pass an initializer list to a Windows Runtime API that expects a collection parameter. 以 StorageItemContentProperties::RetrievePropertiesAsync 为例 。Take StorageItemContentProperties::RetrievePropertiesAsync for example.

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

可以使用类似如下的初始值列表调用该 API。You can call that API with an initializer list like this.

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

在这里,两个因子正在起作用。Two factors are at work here. 第一个,被调用方从初始值列表构建 std::vector(此被调用方是异步的,因此能够拥有该对象,而这是必需的) 。First, the callee constructs a std::vector from the initializer list (this callee is asynchronous, so it's able to own that object, which it must). 第二个,C++/WinRT 透明地(并且不会引入副本)将 std::vector 作为 Windows 运行时集合参数绑定 。Second, C++/WinRT transparently (and without introducing copies) binds std::vector as a Windows Runtime collection parameter.

标准数组和矢量Standard arrays and vectors

winrt::array_view 还有来自 std::vector 和 std::array 的转换构造函数winrt::array_view also has conversion constructors from std::vector and 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

因此,可以改为使用 std::vector 调用 DataWriter::WriteBytes 。So, you could instead call DataWriter::WriteBytes with a 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.

或使用 std::array 。Or with a 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 将 std::vector 作为 Windows 运行时集合参数绑定 。C++/WinRT binds std::vector as a Windows Runtime collection parameter. 因此,可以传递一个 std::vectorwinrt::hstring<,它将转换为 winrt::hstring 的合适 Windows 运行时集合>So, you can pass a std::vector<winrt::hstring>, and it will be converted to the appropriate Windows Runtime collection of winrt::hstring. 如果被调用方是异步的,则需要记住一个额外细节。There's an extra detail to bear in mind if the callee is asynchronous. 由于这种情况的实现细节,需要提供右值,因此必须提供矢量的副本或动作。Due to the implementation details of that case, you'll need to provide an rvalue, so you must provide a copy or a move of the vector. 在以下代码示例中,我们将矢量的所有权移动到异步的被调用方所接受的参数类型的对象(然后在移动之后务必不再访问 vecH)。In the code example below, we move ownership of the vector to the object of the parameter type accepted by the async callee (and then we're careful not to access vecH again after moving it). 如果想要了解有关右值的详细信息,请参阅值类别以及对它们的引用If you want to know more about rvalues, see Value categories, and references to them.

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

但你无法传递需要 Windows 运行时集合的 std::vectorstd::wstring<>But you can't pass a std::vector<std::wstring> where a Windows Runtime collection is expected. 原因在于,由于已经转换为 std::wstring 的合适 Windows 运行时集合,C++ 语言随后不会强制转换该集合的类型参数 。This is because, having converted to the appropriate Windows Runtime collection of std::wstring, the C++ language won't then coerce that collection's type parameter(s). 因此,将不会编译以下代码示例(解决方案将改为传递 std:: vectorwinrt::hstring<,如上所示)>Consequently, the following code example won't compile (and the solution is to pass a std::vector<winrt::hstring> instead, as shown above).

IAsyncAction retrieve_properties_async(StorageFile const& storageFile, std::vector<std::wstring> const& 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, and pointer ranges

请记住,C++ 标准库中将来可能存在等效类型,如果你选择或需要直接使用 winrt::array_view,则还可以这样做 。Bearing in mind the caveat that an equivalent type may exist in the future in the C++ Standard Library, you can also work directly with winrt::array_view if you choose to, or need to.

winrt::array_view 具有来自原始数组和来自一系列 T (指向元素类型的指针)的转换构造函数 *winrt::array_view has conversion constructors from a raw array, and from a range of T* (pointers to the element type).

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 函数和运算符winrt::array_view functions and operators

为 winrt::array_view 实现了大量构造函数、运算符、函数和迭代程序 。A host of constructors, operators, functions, and iterators are implemented for winrt::array_view. winrt::array_view 是一个范围,因此可以将其与基于范围的 或与 std::for_each 一起使用forA winrt::array_view is a range, so you can use it with range-based for, or with std::for_each.

有关更多示例和信息,请参阅 winrt::array_view API 参考主题For more examples and info, see the winrt::array_view API reference topic.

IVectorT< 和标准迭代构造>IVector<T> and standard iteration constructs

SyndicationFeed.Items是 Windows 运行时 API,它返回类型IVectorT 的集合(作为 winrt::Windows::Foundation::Collections::IVector<T> 投影到 C++/WinRT) <>SyndicationFeed.Items is an example of a Windows Runtime API that returns a collection of type IVector<T> (projected into C++/WinRT as winrt::Windows::Foundation::Collections::IVector<T>). 可以将此类型与基于范围的 for 等标准迭代结构一起使用。You can use this type with standard iteration constructs, such as range-based for.

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

具有异步 Windows 运行时 API 的 C++ 协同程序C++ coroutines with asynchronous Windows Runtime APIs

调用异步 Windows 运行时 API 时,可以继续使用并行模式库 (PPL)You can continue to use the Parallel Patterns Library (PPL) when calling asynchronous Windows Runtime APIs. 但在许多情况下,C++ 协同程序为与异步对象进行交互提供了一种高效且易于编码的习惯用法。However, in many cases, C++ coroutines provide an efficient and more easily-coded idiom for interacting with asynchronous objects. 详细信息和代码示例,请参阅利用 C++/WinRT 实现的并发和异步运算For more info, and code examples, see Concurrency and asynchronous operations with C++/WinRT.

重要的 APIImportant APIs