I want to implement a C++ WinRT IBuffer that wraps a char* buffer, so i can use it with WinRT WriteAsync/ReadAsync operations that accept an IBuffer^ parameter.
EDIT 1 (clarification)
I want to avoid data copy.
This should work:
// Windows::Storage::Streams::DataWriter
// Windows::Storage::Streams::IBuffer
// BYTE = unsigned char (could be char too)
BYTE input[1024] {};
DataWriter ^writer = ref new DataWriter();
writer->WriteBytes(Platform::ArrayReference<BYTE>(input, sizeof(input));
IBuffer ^buffer = writer->DetachBuffer();
Mostly copied from http://jeremiahmorrill.wordpress.com/2012/05/11/http-winrt-client-for-c/ but adapted to directly wrap my own byte[]:
NativeBuffer.h:
#pragma once
#include <wrl.h>
#include <wrl/implements.h>
#include <windows.storage.streams.h>
#include <robuffer.h>
#include <vector>
// todo: namespace
class NativeBuffer :
public Microsoft::WRL::RuntimeClass<Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::RuntimeClassType::WinRtClassicComMix>,
ABI::Windows::Storage::Streams::IBuffer,
Windows::Storage::Streams::IBufferByteAccess>
{
public:
virtual ~NativeBuffer()
{
}
STDMETHODIMP RuntimeClassInitialize(byte *buffer, UINT totalSize)
{
m_length = totalSize;
m_buffer = buffer;
return S_OK;
}
STDMETHODIMP Buffer(byte **value)
{
*value = m_buffer;
return S_OK;
}
STDMETHODIMP get_Capacity(UINT32 *value)
{
*value = m_length;
return S_OK;
}
STDMETHODIMP get_Length(UINT32 *value)
{
*value = m_length;
return S_OK;
}
STDMETHODIMP put_Length(UINT32 value)
{
m_length = value;
return S_OK;
}
private:
UINT32 m_length;
byte *m_buffer;
};
To create the IBuffer:
Streams::IBuffer ^CreateNativeBuffer(LPVOID lpBuffer, DWORD nNumberOfBytes)
{
Microsoft::WRL::ComPtr<NativeBuffer> nativeBuffer;
Microsoft::WRL::Details::MakeAndInitialize<NativeBuffer>(&nativeBuffer, (byte *)lpBuffer, nNumberOfBytes);
auto iinspectable = (IInspectable *)reinterpret_cast<IInspectable *>(nativeBuffer.Get());
Streams::IBuffer ^buffer = reinterpret_cast<Streams::IBuffer ^>(iinspectable);
return buffer;
}
And the call to read data (lpBuffer is the byte[]):
Streams::IBuffer ^buffer = CreateNativeBuffer(lpBuffer, nNumberOfbytes);
create_task(randomAccessStream->ReadAsync(buffer, (unsigned int)nNumberOfBytesToRead, Streams::InputStreamOptions::None)).wait();
I am not so sure if the ComPtr needs some cleanup, so any suggestions regarding memory management are welcome.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With