將參數傳入到 ABI 界限Passing parameters into the ABI boundary

透過 winrt::param 命名空間中的類型,C++/WinRT 可藉由在一般情況提供自動轉換,簡化將參數傳入 ABI 界線的過程。With the types in the winrt::param namespace, C++/WinRT simplifies passing parameters into the ABI boundary by providing automatic conversions for common cases. 您可以在字串處理標準 C++ 資料類型和 C++/WinRT 中看到更多詳細資料和程式碼範例。You can see more details, and code examples, in String handling and Standard C++ data types and C++/WinRT.

重要

您不會自己使用 winrt::param 命名空間中的類型。You shouldn't use the types in the winrt::param namespace yourself. 這些類型是為了用於投影。They're for the benefit of the projection.

許多類型都有同步和非同步版本。Many types come in both synchronous and asynchronous versions. C++/WinRT 會在您將參數傳遞給同步方法時使用同步版本;在您將參數傳遞給非同步方法時使用非同步版本。C++/WinRT uses the synchronous version when you're passing a parameter to a synchronous method; it uses the asynchronous version when you're passing a parameter to an asynchronous method. 非同步版本會採用額外的步驟,使得呼叫者難以在作業完成之前改變集合。The asynchronous version takes extra steps to make it harder for the caller to mutate the collection before the operation has completed. 不過,要注意的是,並沒有任何變體可防止從另一個執行緒改變集合。Note, however, that none of the variants protect against the collection being mutated from another thread. 避免此狀況是您的責任。Preventing that is your responsibility.

字串參數String parameters

winrt::param::hstring 可讓參數更容易地傳遞至採用 HSTRING 的 API。winrt::param::hstring simplifies passing parameters to APIs that take HSTRING.

您可以傳遞的類型Types that you can pass 附註Notes
{} 傳遞空白字串。Passes empty string.
winrt::hstringwinrt::hstring
std::wstring_viewstd::wstring_view 針對常值,您可以撰寫 L"Name"svFor literals, you can write L"Name"sv. 檢視必須在結束之後有 null 結束字元。The view must have a null terminator after the end.
std::wstringstd::wstring -
wchar_t const*wchar_t const* null 終止的字串。A null-terminated string.

不允許使用 nullptrnullptr is not allowed. 請改為使用 {}Use {} instead.

編譯器會知道如何在編譯時評估字串常值上的 wcslenThe compiler knows how to evaluate wcslen on string literals at compile time. 因此,常值的 L"Name"svL"Name" 會相等。So, for literals, L"Name"sv and L"Name" are equivalent.

請注意,std::wstring_view 物件都不是以 null 終止,但 C++/WinRT 需要字串結束後的字元是 null。Note that std::wstring_view objects are not null terminated, but C++/WinRT requires that the character after the end of the string be a null. 如果您傳遞非 null 終止的 std::wstring_view,則會終止處理程序。If you pass a non-null-terminated std::wstring_view, then the process will terminate.

可反覆 (Iterable) 的參數Iterable parameters

winrt::param::iterable<T>winrt::param::async_iterable<T> 可讓參數更容易地傳遞至採用 IIterable<T> 的 API。winrt::param::iterable<T> and winrt::param::async_iterable<T> simplify passing parameters to APIs that take IIterable<T>.

Windows 執行階段集合已是 IIterable 狀態。Windows Runtime collections are already IIterable.

您可以傳遞的類型Types that you can pass 同步Sync AsyncAsync 附註Notes
nullptr Yes Yes 您必須確認基礎方法可支援 nullptrYou must verify that the underlying method supports nullptr.
IIterable<T>IIterable<T> Yes Yes 或可以轉換成該類型的任何項目。Or anything convertible to it.
std::vector<T> const&std::vector<T> const& Yes No
std::vector<T>&&std::vector<T>&& Yes Yes 內容會移到迭代器中,以避免發生變更。Contents are moved into the iterator to prevent mutation.
std::initializer_list<T>std::initializer_list<T> Yes Yes 非同步版本會複製這些項目。The async version copies the items.
std::initializer_list<U>std::initializer_list<U> Yes No U 必須可轉換成 TU must be convertible to T.
{ ForwardIt begin, ForwardIt end } Yes No *begin 必須可轉換成 T*begin must be convertible to T.

請注意,IIterable<U>std::vector<U> 是不允許的項目,即使 U 可轉換成 T 也一樣。針對 std::vector<U> ,您可以使用雙重迭代器版本 (詳細資料如下)。Note that IIterable<U> and std::vector<U> are not permitted, even if U is convertible to T. For std::vector<U>, you can use the double-iterator version (more details below).

在某些情況下,您擁有的物件可能已實作您想要的 IIterableIn some cases, the object that you have may actually implement the IIterable that you want. 例如,FileOpenPicker.PickMultipleFilesAsync 產生的 IVectorView<StorageFile> 會實作 IIterable<StorageFile>For example, the IVectorView<StorageFile> produced by FileOpenPicker.PickMultipleFilesAsync implements IIterable<StorageFile>. 但也會實作 IIterable<IStorageItem> ;您只需要明確要求即可。But it also implements IIterable<IStorageItem>; you just have to ask for it explicitly.

IVectorView<StorageFile> pickedFiles{ co_await filePicker.PickMultipleFilesAsync() };
requestData.SetStorageItems(storageItems.as<IIterable<IStorageItem>>());

在其他情況下,您可以使用雙重迭代器版本。In other cases, you can use the double-iterator version.

std::vector<StorageFile> storageFiles;
requestData.SetStorageItems({ storageFiles.begin(), storageFiles.end() });

雙重迭代器可更廣泛地用於不符合上述任何案例的集合,只要您可以對其反覆查看,並產生可以轉換成 T 的事項即可。我們先前已將其用於反覆查看衍生類型的向量。The double-iterator works more generally for the case where you have a collection that doesn't fit any of the scenarios above, as long as you can iterate over it and produce things that can be converted to T. We used it above to iterate over a vector of derived types. 在這裡,我們用其來反覆查看衍生類型的非向量部分。Here, we use it to iterate over a non-vector of derived types.

std::array<StorageFile, 3> storageFiles;
requestData.SetStorageItems(storageFiles); // This doesn't work.
requestData.SetStorageItems({ storageFiles.begin(), storageFiles.end() }); // But this works.

如果迭代器是 RandomAcessIt,則 IIterator<T>.GetMany(T[]) 的實作會更有效率。The implementation of IIterator<T>.GetMany(T[]) is more efficient if the iterator is a RandomAcessIt. 否則,其會讓數個傳遞超出範圍。Otherwise, it makes several passes over the range.

您可以傳遞的類型Types that you can pass 同步Sync AsyncAsync 附註Notes
nullptr Yes Yes 您必須確認基礎方法可支援 nullptrYou must verify that the underlying method supports nullptr.
IIterable<IKeyValuePair<K, V>>IIterable<IKeyValuePair<K, V>> Yes Yes 或可以轉換成該類型的任何項目。Or anything convertible to it.
std::map<K, V> const&std::map<K, V> const& Yes No
std::map<K, V>&&std::map<K, V>&& Yes Yes 內容會移到迭代器中,以避免發生變更。Contents are moved into the iterator to prevent mutation.
std::unordered_map<K, V> const&std::unordered_map<K, V> const& Yes No
std::unordered_map<K, V>&&std::unordered_map<K, V>&& Yes Yes 內容會移到迭代器中,以避免發生變更。Contents are moved into the iterator to prevent mutation.
std::initializer_list<std::pair<K, V>>std::initializer_list<std::pair<K, V>> Yes Yes KV 類型必須完全相符。Types K and V must match exactly. 索引鍵不得重複。Keys may not be duplicated. 非同步版本會複製這些項目。The async version copies the items.
{ ForwardIt begin, ForwardIt end } Yes No begin->firstbegin->second 必須可分別轉換成 KVbegin->first and begin->second must be convertible to K and V, respectively.

向量檢視參數Vector view parameters

winrt::param::vector_view<T>winrt::param::async_vector_view<T> 可讓參數更容易地傳遞至採用 IVectorView<T> 的 API。winrt::param::vector_view<T> and winrt::param::async_vector_view<T> simplify passing parameters to APIs that take IVectorView<T>.

您可以使用 IVector<T>.GetViewIVector 取得 IVectorViewYou can use IVector<T>.GetView to get an IVectorView from an IVector.

您可以傳遞的類型Types that you can pass 同步Sync AsyncAsync 附註Notes
nullptr Yes Yes 您必須確認基礎方法可支援 nullptrYou must verify that the underlying method supports nullptr.
IVectorView<T>IVectorView<T> Yes Yes 或可以轉換成該類型的任何項目。Or anything convertible to it.
std::vector<T>const&std::vector<T>const& Yes No
std::vector<T>&&std::vector<T>&& Yes Yes 內容會移到檢視中,以避免發生變更。Contents are moved into the view to prevent mutation.
std::initializer_list<T>std::initializer_list<T> Yes Yes 類型必須完全相符。Type must match exactly. 非同步版本會複製這些項目。The async version copies the items.
{ ForwardIt begin, ForwardIt end } Yes No *begin 必須可轉換成 T*begin must be convertible to T.

雙重迭代器版本可用來另外建立不符合直接傳遞需求的向量檢視。The double-iterator version can be used to create vector views out of things that don't fit the requirements for being passed directly. 不過,請注意,由於向量支援隨機存取,因此我們建議您傳遞 RandomAcessIterNote, however, that since vectors support random access, we recommend that you pass a RandomAcessIter.

對應檢視參數Map view parameters

winrt::param::map_view<T>winrt::param::async_map_view<T> 可讓參數更容易地傳遞至採用 IMapView<T> 的 API。winrt::param::map_view<T> and winrt::param::async_map_view<T> simplify passing parameters to APIs that take IMapView<T>.

您可以使用 IMap::GetViewIMap 取得 IMapViewYou can use IMap::GetView to get an IMapView from an IMap.

您可以傳遞的類型Types that you can pass 同步Sync AsyncAsync 附註Notes
nullptr Yes Yes 您必須確認基礎方法可支援 nullptrYou must verify that the underlying method supports nullptr.
IMapView<K, V>IMapView<K, V> Yes Yes 或可以轉換成該類型的任何項目。Or anything convertible to it.
std::map<K, V> const&std::map<K, V> const& Yes No
std::map<K, V>&&std::map<K, V>&& Yes Yes 內容會移到檢視中,以避免發生變更。Contents are moved into the view to prevent mutation.
std::unordered_map<K, V> const&std::unordered_map<K, V> const& Yes No
std::unordered_map<K, V>&&std::unordered_map<K, V>&& Yes Yes 內容會移到檢視中,以避免發生變更。Contents are moved into the view to prevent mutation.
std::initializer_list<std::pair<K, V>>std::initializer_list<std::pair<K, V>> Yes Yes 同步和非同步版本皆會複製這些項目。Both sync and async versions copy the items. 您不得複製索引鍵。You may not duplicate keys.

向量參數Vector parameters

winrt::param::vector<T> 可讓參數更容易地傳遞至採用 IVector<T> 的 API。winrt::param::vector<T> simplifies passing parameters to APIs that take IVector<T>.

您可以傳遞的類型Types that you can pass 附註Notes
nullptr 您必須確認基礎方法可支援 nullptrYou must verify that the underlying method supports nullptr.
IVector<T>IVector<T> 或可以轉換成該類型的任何項目。Or anything convertible to it.
std::vector<T>&&std::vector<T>&& 內容會移到參數中,以避免發生變更。Contents are moved into the parameter to prevent mutation. 結果不會移回。Results are not moved back.
std::initializer_list<T>std::initializer_list<T> 內容會複製到參數中,以避免發生變更。Contents are copied into the parameter to prevent mutation.

如果方法會改變向量,則觀察變化的唯一方式是直接傳遞 IVectorIf the method mutates the vector, then the only way to observe the mutation is to pass an IVector directly. 如果您傳遞 std::vector,則方法會改變複製項目,而不是改變原始項目。If you pass a std::vector, then the method mutates the copy and not the original.

對應無參數Map parameters

winrt::param::map<T> 可讓參數更容易地傳遞至採用 IMap<T> 的 API。winrt::param::map<T> simplifies passing parameters to APIs that take IMap<T>.

您可以傳遞的類型Types that you can pass 附註Notes
nullptr 您必須確認基礎方法可支援 nullptrYou must verify that the underlying method supports nullptr.
IMap<T>IMap<T> 或可以轉換成該類型的任何項目。Or anything convertible to it.
std::map<K, V>&&std::map<K, V>&& 內容會移到參數中,以避免發生變更。Contents are moved into the parameter to prevent mutation. 結果不會移回。Results are not moved back.
std::unordered_map<K, V>&&std::unordered_map<K, V>&& 內容會移到參數中,以避免發生變更。Contents are moved into the parameter to prevent mutation. 結果不會移回。Results are not moved back.
std::initializer_list<std::pair<K, V>>std::initializer_list<std::pair<K, V>> 內容會複製到參數中,以避免發生變更。Contents are copied into the parameter to prevent mutation.

如果方法會改變對應,則觀察變化的唯一方式是直接傳遞 IMapIf the method mutates the map, then the only way to observe the mutation is to pass an IMap directly. 如果您傳遞 std::mapstd::unordered_map,則方法會改變複製項目,而不是改變原始項目。If you pass a std::map or std::unordered_map, then the method mutates the copy and not the original.

陣列參數Array parameters

winrt::array_view<T> 不在 winrt::param 命名空間中,但其會用於 C 樣式陣列—亦稱為一致陣列的參數。The winrt::array_view<T> is not in the winrt::param namespace, but it is used for parameters that are C-style arrays—also known as conformant arrays.

您可以傳遞的類型Types that you can pass 附註Notes
{} 空的陣列。An empty array.
arrayarray C 的一致陣列 (亦即 C array[N];),其中 C 可轉換成 T,而且 sizeof(C) == sizeof(T)A conformant array of C (that is, C array[N];), where C is convertible to T, and sizeof(C) == sizeof(T).
std::array<C, N>std::array<C, N> C 的 C++ std::array,其中 C 可轉換成 T,而且 sizeof(C) == sizeof(T)A C++ std::array of C, where C is convertible to T, and sizeof(C) == sizeof(T).
std::vectorstd::vector C 的 C++ std::vector,其中 C 可轉換成 T,而且 sizeof(C) == sizeof(T)A C++ std::vector of C, where C is convertible to T, and sizeof(C) == sizeof(T).
{ T*, T* } 一組指標代表範圍 [開始、結束]。A pair of pointers represent the range [begin, end).
std::initializer_list<T>std::initializer_list<T>

另請參閱部落格文章:將 C 樣式陣列傳遞到 Windows 執行階段 ABI 界限的各種模式Also see the blog post The various patterns for passing C-style arrays across the Windows Runtime ABI boundary.