Getting an array of bytes out of Windows::Storage::Streams::IBuffer
Asked Answered
C

7

15

I have an object that implements the interface Windows::Storage::Streams::IBuffer, and I want to get an array of bytes out of it, however while looking at the documentation this interface looks pretty useless, and the documentation does not offer any reference to any other class that could be combined with this interface to achieve my purpose. All I have found so far with google is a reference to the .Net class WindowsRuntimeBufferExtensions but I am using C++ so this is also a dead end.

Can someone give a hint on how to get an array of bytes from Windows::Storage::Streams::IBuffer in C++?

Craddock answered 7/8, 2012 at 20:43 Comment(0)
R
12

You can use IBufferByteAccess, through exotic COM casts:

byte* GetPointerToPixelData(IBuffer^ buffer)
{
   // Cast to Object^, then to its underlying IInspectable interface.

   Object^ obj = buffer;
   ComPtr<IInspectable> insp(reinterpret_cast<IInspectable*>(obj));

   // Query the IBufferByteAccess interface.
   ComPtr<IBufferByteAccess> bufferByteAccess;
   ThrowIfFailed(insp.As(&bufferByteAccess));

   // Retrieve the buffer data.

   byte* pixels = nullptr;
   ThrowIfFailed(bufferByteAccess->Buffer(&pixels));

   return pixels;

}

Code sample copied from http://cm-bloggers.blogspot.fi/2012/09/accessing-image-pixel-data-in-ccx.html

Recapitulation answered 5/1, 2013 at 14:12 Comment(1)
I changed my implementation and I am using this approach now since it improves the performance of my app. Thanks.Craddock
I
9

This is a C++/CX version:

std::vector<unsigned char> getData( ::Windows::Storage::Streams::IBuffer^ buf )
{
    auto reader = ::Windows::Storage::Streams::DataReader::FromBuffer(buf);

    std::vector<unsigned char> data(reader->UnconsumedBufferLength);

    if ( !data.empty() )
        reader->ReadBytes(
            ::Platform::ArrayReference<unsigned char>(
                &data[0], data.size()));

    return data;
}

For more information see Array and WriteOnlyArray (C++/CX).

Ides answered 17/1, 2013 at 16:39 Comment(0)
A
9

Also check this method:

IBuffer -> Platform::Array
CryptographicBuffer.CopyToByteArray

Platform::Array -> IBuffer
CryptographicBuffer.CreateFromByteArray

As a side note, if you want to create Platform::Array from simple C++ array you could use Platform::ArrayReference, for example:

char* c = "sdsd";
Platform::ArrayReference<unsigned char> arraywrapper((unsigned char*) c, sizeof(c));
Accelerator answered 20/5, 2013 at 8:57 Comment(2)
Thanks this saved me a headache!, for reference, ArrayReference is in the Platform namespace.Sciomancy
WARNING: sizeof(c) will produce the size of the pointer, not the length of the string.Neurogenic
C
5

As mentioned before, WindowsRuntimeBufferExtensions from the namespace System::Runtime::InteropServices::WindowsRuntime is only available for .Net applications and not for native C++ applications.

A possible solution would be to use Windows::Storage::Streams::DataReader:

void process(Windows::Storage::Streams::IBuffer^ uselessBuffer)
{
    Windows::Storage::Streams::DataReader^ uselessReader =
             Windows::Storage::Streams::DataReader::FromBuffer(uselessBuffer);
    Platform::Array<Byte>^ managedBytes = 
                         ref new Platform::Array<Byte>(uselessBuffer->Length);
    uselessReader->ReadBytes( managedBytes );                               
    BYTE * bytes = new BYTE[uselessBuffer->Length];
    for(int i = 0; i < uselessBuffer->Length; i++)
        bytes[i] = managedBytes[i];

    (...)
}
Craddock answered 13/8, 2012 at 20:12 Comment(0)
L
4

Since this question is tagged , here's a solution using C++/WinRT. It essentially does the same as this answer under the hood, but is way more accessible. The (undocumented) data() helper on the IBuffer projection does all the heavy lifting:

uint8_t* GetPointerToPixelData(::winrt::Windows::Storage::Streams::IBuffer const& buffer)
{
    return buffer.data();
}

There is unfortunately no official documentation (yet), and I only stumbled across this in the sample code for the WritableBitmap.PixelBuffer property (make sure to select "C++/WinRT" from the language dropdown at the top right).

An identical solution (by explicitly querying for the IBufferByteAccess interface) is also available from that documentation entry when selecting "C++/CX" from the language dropdown.


Update 2022-10-15

Since writing this answer the documentation has been updated. The winrt namespace documentation now has a section called C++/WinRT functions that extend Windows Runtime APIs that lists Windows Runtime types alongside the C++/WinRT functions available in addition to the interface projections.

The IBuffer C++/WinRT extension functions link takes you to the respective section in the IBuffer interface documentation, with the data() function properly documented.

Lifesaver answered 3/5, 2019 at 17:54 Comment(0)
N
3

This should work with WinRT extensions:

// Windows::Storage::Streams::DataReader
// buffer is assumed to be of type Windows::Storage::Streams::IBuffer
// BYTE = unsigned char

DataReader^ reader = DataReader::FromBuffer(buffer);

BYTE *extracted = new BYTE[buffer->Length];

// NOTE: This will read directly into the allocated "extracted" buffer
reader->ReadBytes(Platform::ArrayReference<BYTE>(extracted, buffer->Length));

// ... do something with extracted...

delete [] extracted; // don't forget to free the space
Neurogenic answered 13/3, 2015 at 13:45 Comment(2)
There is almost no documentation about this class Platform::ArrayReference, where did you find this information if I may ask?Craddock
Here's an example from MSDN msdn.microsoft.com/en-us/library/hh700131.aspx "Use ArrayReference to avoid copying data"Neurogenic
I
-1

Use the extension method like a static method:

IBuffer *buffer;
array<unsigned char>^ result= System::Runtime::InteropServices::WindowsRuntime::WindowsRuntimeBufferExtensions::ToArray(buffer);
Instructor answered 7/8, 2012 at 20:55 Comment(2)
@user787913, I was confused at first as well.Instructor
@Instructor WindowsRuntimeBufferExtensions is a class in .Net framework, it cannot be used from a native C++ applicationAnglican

© 2022 - 2024 — McMap. All rights reserved.