Search code examples
windows-runtimec++-winrt

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


I am currently porting an UWP application from C++/CX to C++/WinRT. I encountered a safe_cast<Platform::IBoxArray<byte>^>(data) where data is of type Windows::Foundation::IInspectable ^.

I know that the safe_cast is represented by the as<T> method, and I know there are functions for boxing (winrt::box_value) and unboxing (winrt::unbox_value) in WinRT/C++.

However, I need to know the equivalent of Platform::IBoxArray in order to perform the cast (QueryInterface). According to https://learn.microsoft.com/de-de/cpp/cppcx/platform-iboxarray-interface?view=vs-2017, IBoxArray is the C++/CX equivalent of Windows::Foundation::IReferenceArray, but there is no winrt::Windows::Foundation::IReferenceArray...

Update for nackground: What I am trying to achieve is retrieving the view transform attached by the HoloLens to every Media Foundation sample from its camera. My code is based on https://github.com/Microsoft/HoloLensForCV, and I got really everything working except for this last step. The problem is located around this piece of code:

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

Solution

  • I'm also working on porting some code from HoloLensForCV to C++/WinRT. I came up with the following solution for a very similar case (but not the exact same line of code you ask about):

    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()) };
    

    Specifically, you can replace the safe_cast with .as<Windows::Foundation::IReferenceArray<std::uint8_t> for a boxed array of bytes. Then, I suspect doing the same cast as me (except to float4x4* instead of wchar_t*) will work for you.

    The /ZW flag is not required for my example above.