使用 C++/WinRT 時,您可以使用標準 C++ 資料型別呼叫 Windows 執行階段 API,包括部分 C++ 標準函式庫的資料型態。 你可以把標準字串傳給 API(參見 C++/WinRT 中的字串處理),也可以把初始化器清單和標準容器傳給期望語義等價集合的 API。
另見 「將參數傳入 ABI 邊界」。
標準初始化器列表
初始化器清單(std::initializer_list)是一種 C++ 標準函式庫的結構。 當你呼叫某些 Windows 執行階段 建構子和方法時,可以使用初始化器清單。 例如,你可以用 1 來呼叫 DataWriter::WriteBytes 。
#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.
}
讓這一切運作起來,涉及兩個環節。 首先, DataWriter::WriteBytes 方法會取一個 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.h)。
第二, winrt::array_view 有一個初始化者列表建構子。
template <typename T> winrt::array_view(std::initializer_list<T> value) noexcept
在很多情況下,你可以選擇是否要在程式中注意 winrt::array_view 。 如果你選擇 不 去知道它,那麼當 C++ 標準函式庫出現等效型別時,你就沒有程式碼需要更改。
你可以將初始化器清單傳給期望集合參數的 Windows 執行階段 API。 以 StorageItemContentProperties::RetrievePropertiesAsync 為例。
IAsyncOperation<IMap<winrt::hstring, IInspectable>> StorageItemContentProperties::RetrievePropertiesAsync(IIterable<winrt::hstring> propertiesToRetrieve) const;
你可以用這樣的初始化器清單呼叫該 API。
IAsyncAction retrieve_properties_async(StorageFile const storageFile)
{
auto properties{ co_await storageFile.Properties().RetrievePropertiesAsync({ L"System.ItemUrl" }) };
}
這裡有兩個因素在起作用。 首先,被呼叫端會從初始化串列建構一個 std::vector(這個被呼叫端是非同步的,因此它能夠擁有該物件,而且也必須這麼做)。 其次,C++/WinRT 透明地(且不引入副本)將 std::vector 綁定為 Windows 執行階段 集合參數。
標準陣列與向量
WinRT::array_view 也有來自 STD::vector 和 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
所以,你可以改用 DataWriter::WriteBytes ,並用 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。
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 執行階段 集合參數。 所以,你可以傳遞一個 std::vector<winrt::hstring>,然後它會被轉換成正確的 Windows 執行階段 集合 winrt::hstring。 如果被叫方是非同步,還有一個額外細節需要注意。 根據該案例的實作細節,你需要提供一個 r值,因此你必須提供向量的複製或移動。 在下面的程式碼範例中,我們將該向量的所有權轉移給非同步被呼叫端所接受之參數型別的物件(然後在轉移之後,我們會注意不再存取 vecH)。 如果你想了解更多關於r值的資訊,請參閱 「值類別」及其相關參考資料。
IAsyncAction retrieve_properties_async(StorageFile const storageFile, std::vector<winrt::hstring> vecH)
{
auto properties{ co_await storageFile.Properties().RetrievePropertiesAsync(std::move(vecH)) };
}
但在預期使用 Windows 執行階段 集合的地方,你無法傳遞 std::vector<std::wstring>。 這是因為,當 C++ 語言轉換成適當的 Windows 執行階段 集合 std::wstring 後,就不會強制執行該集合的型別參數。 因此,以下範例的程式碼無法編譯(解決方法是如上所示,傳入 std::vector<winrt::hstring> )。
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.
}
原始陣列與指標範圍
考慮到未來 C++ 標準函式庫中可能存在等價型別,你也可以直接使用 winrt::array_view ,如果你願意或需要這麼做。
winrt::array_view 具有可從原始陣列轉換而來的建構函式,以及可從一段 T* 範圍(亦即指向元素類型的指標)轉換而來的建構函式。
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 實作了許多構造子、運算子、函式和迭代器。
winrt::array_view 是一種範圍,因此你可以將它與以範圍為基礎的 for 搭配使用,或與 std::for_each 搭配使用。
更多範例與資訊,請參閱 winrt::array_view API 參考主題。
IVector<T> 與標準迭代結構
SyndicationFeed.Items 是一個 Windows 執行階段 API 範例,該 API 回傳 IVector<T> 型別的集合(在 C++/WinRT 中投影為 winrt::Windows::Foundation::Collections::IVector<T>)。 你可以將此類型用於標準迭代結構,例如基於 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++ 協程
呼叫非同步 Windows 執行階段 API 時,仍可繼續使用平行模式函式庫(PPL)。 然而,在許多情況下,C++ 協程提供了一種更有效率且易於編碼的語言,用於與非同步物件互動。 更多資訊與程式碼範例,請參見 C++/WinRT 的並行與非同步操作。