等同于 C++/WinRT 中的 Platform::IBoxArray

Equivalent of Platform::IBoxArray in C++/WinRT

我目前正在将 UWP 应用程序从 C++/CX 移植到 C++/WinRT。我遇到了 safe_cast<Platform::IBoxArray<byte>^>(data),其中 data 的类型是 Windows::Foundation::IInspectable ^

我知道safe_cast是用as<T>方法表示的,我知道里面有装箱(winrt::box_value)和拆箱(winrt::unbox_value)的函数WinRT/C++.

但是,我需要知道 Platform::IBoxArray 的等效项才能执行转换 (QueryInterface)。根据 https://docs.microsoft.com/de-de/cpp/cppcx/platform-iboxarray-interface?view=vs-2017IBoxArrayWindows::Foundation::IReferenceArray 的 C++/CX 等价物,但没有 winrt::Windows::Foundation::IReferenceArray...

nackground 更新: 我想要实现的是从其相机中检索 HoloLens 附加到每个 Media Foundation 样本的视图变换。我的代码基于 https://github.com/Microsoft/HoloLensForCV,除了这最后一步之外,我真的一切正常。问题出在这段代码附近:

static const GUID MF_EXTENSION_VIEW_TRANSFORM = {
    0x4e251fa4, 0x830f, 0x4770, 0x85, 0x9a, 0x4b, 0x8d, 0x99, 0xaa, 0x80, 0x9b
};

// ...

// In the event handler, which receives const winrt::Windows::Media::Capture::Frames::MediaFrameReader& sender:

auto frame = sender.TryAcquireLatestFrame();
// ...

if (frame.Properties().HasKey(MF_EXTENSION_VIEW_TRANSFORM)) {
    auto /* IInspectable */ userData = frame.Properties().Lookup(MF_EXTENSION_VIEW_TRANSFORM);

    // Now I would have to do the following:
    // auto userBytes = safe_cast<Platform::IBoxArray<Byte> ^>(userData)->Value;
    //viewTransform = *reinterpret_cast<float4x4 *>(userBytes.Data);
}

我不敢相信这真的有效,但使用来自 https://docs.microsoft.com/de-de/windows/uwp/cpp-and-winrt-apis/interop-winrt-cx 的信息,我想出了以下解决方案:

通过 /ZW 启用 "Consume Windows Runtime Extension" 并使用以下转换:

auto abi = reinterpret_cast<Platform::Object ^>(winrt::get_abi(userData));
auto userBytes = safe_cast<Platform::IBoxArray<byte> ^>(abi)->Value;
viewTransform = *reinterpret_cast<float4x4 *>(userBytes->Data);

不幸的是,解决方案的缺点是生成

warning C4447: 'main' signature found without threading model. Consider using 'int main(Platform::Array^ args)'.

但是现在,我可以忍受...

我还在努力将一些代码从 HoloLensForCV 移植到 C++/WinRT。我针对一个非常相似的案例提出了以下解决方案(但不是您询问的完全相同的代码行):

auto user_data = source.Info().Properties().Lookup(c_MF_MT_USER_DATA); // type documented as 'array of bytes'
auto source_name = user_data.as<Windows::Foundation::IReferenceArray<std::uint8_t>>(); // Trial and error to get the right specialization of IReferenceArray
winrt::com_array<std::uint8_t> arr;
source_name.GetUInt8Array(arr);
winrt::hstring source_name_str{ reinterpret_cast<wchar_t*>(arr.data()) };

具体来说,对于盒装字节数组,您可以将 safe_cast 替换为 .as<Windows::Foundation::IReferenceArray<std::uint8_t>。然后,我怀疑做和我一样的转换(除了 float4x4* 而不是 wchar_t*)对你有用。

上面的示例不需要 /ZW 标志。