如何将字节复制到 Windows::Storage::Streams::Buffer 或通过 Windows::Storage::Streams::DataWriter::WriteBuffer() 缓冲输出

how to copy bytes into a Windows::Storage::Streams::Buffer or IBuffer for ouput via Windows::Storage::Streams::DataWriter::WriteBuffer()

我正在使用一个示例 UWP C++/CX 程序创建两个 UDP 网络通信线程,它们使用 Windows::Storage::Streams::DataWriterWindows::Storage::Streams::DataReader 相互发送数据,同时更新显示的 window 显示来回的数据。

使用 Platform::String 变量和 DataWriter->WriteString() 的初始实现工作正常。但是现在我想实现一个二进制协议,它具有包含各种类型信息的可变长度缓冲区。

DataReader->ReadBuffer()DataWriter->WriteBuffer() 需要 Windows::Storage::Streams::Buffer.

要访问 ReadBuffer() 返回的缓冲区,我正在使用一个函数,如果可以在 Obtaining pointers to data buffers (C++/CX) which is similar to an answer in Getting an array of bytes out of Windows::Storage::Streams::IBuffer

的网络上找到该函数的源代码
#include <robuffer.h>  

byte* GetPointerToPixelData(IBuffer^ pixelBuffer, unsigned int *length)
{
    if (length != nullptr)
    {
        *length = pixelBuffer->Length;
    }
    // Query the IBufferByteAccess interface.  
    Microsoft::WRL::ComPtr<IBufferByteAccess> bufferByteAccess;
    reinterpret_cast<IInspectable*>(pixelBuffer)->QueryInterface(IID_PPV_ARGS(&bufferByteAccess));

    // Retrieve the buffer data.  
    byte* pixels = nullptr;
    bufferByteAccess->Buffer(&pixels);
    return pixels;
}

但是我一直无法找到如何将本机结构复制到缓冲区中,以便可以使用 DataWriter->WriteBuffer() 将其发送出去。

如果我有一些二进制数据结构,我如何将这个结构的内容复制到输出 Windows::Storage::Streams::Buffer 以便与 DataWriter->WriteBuffer() 一起使用?

看来,可用于获取指向 Buffer 内存区域的指针以将数据从 Buffer 复制到本机内存区域的同一函数也可用于获取可用于将数据复制到 Buffer 中的指针。另见 Obtaining pointers to data buffers (C++/CX). and see as well COM Coding Practices for information about the IID_PPV_ARGS() macro and the ATL smart pointer class CComPtr. See QueryInterface: Navigating in an Object

ComPtr 是 ATL CComPtr 的 WRL 版本(请参阅 Native WinRT Inheritance as well as Windows Runtime C++ Template Library (WRL),其中包含指向 WRL 和 WinRT 的各种支持主题的链接)。

(ComPtr is a WRL smart pointer. It automates some aspects of COM that otherwise get tedious fast. It’s similar to ATL’s CComPtr, although some operations that CComPtr performed implicitly now require explicit code, largely because those implicit operations were responsible for a lot of bugs in code written by people who didn’t really understand how CComPtr works. With the new ComPtr, a failure to understand how it works is more likely to lead to a compiler error than a runtime bug.)

以及ComPtr in the DirectXTK wiki

Microsoft::WRL::ComPtr is a C++ template smart-pointer for COM objects that is used extensively in Windows Runtime (WinRT) C++ programming. It works in Win32 desktop applications as well. It is similar to ATL's CComPtr with some useful improvements. Microsoft::WRL:::ComPtr is in the Windows 8.x SDK and Windows 10 SDK, which, unlike ATL, is available when using the Express versions of Visual Studio. It is used extensively in DirectX Tool Kit to properly handle COM reference counting maintenance.

#include <robuffer.h>  

byte* GetPointerToPixelData(IBuffer^ pixelBuffer, unsigned int *length)
{
    if (length != nullptr)
    {
        *length = pixelBuffer->Length;
    }
    // Query the IBufferByteAccess interface.  
    Microsoft::WRL::ComPtr<IBufferByteAccess> bufferByteAccess;
    reinterpret_cast<IInspectable*>(pixelBuffer)->QueryInterface(IID_PPV_ARGS(&bufferByteAccess));

    // Retrieve the buffer data.  
    byte* pixels = nullptr;
    bufferByteAccess->Buffer(&pixels);
    return pixels;
}

警告:您必须确保不超过分配给Buffer的内存容量(您可以检查Capacity属性缓冲区)。从本机变量复制到 Buffer 后,您还必须将 Length 属性设置为 Buffer.

中数据集的实际字节数

例如:

// test structs for binary data to parse.
struct struct1 {
    unsigned char uchMajorClass;
    unsigned char uchMinorClass;
    long  lVal1;
};

void testfunc (IOutputStream^ outputStream)
{
    auto dataWriter = ref new DataWriter(outputStream);

    struct1 myStruct1 = { 1, 11,0 };

    Buffer ^myBuffer = ref new Buffer(sizeof(struct1));  // allocate Buffer of desired size

    unsigned int  len;
    struct1 *sp = (struct1 *)GetPointerToPixelData(myBuffer, &len);  // get native pointer

    // we could use myBuffer->Capacity at this point to check the capacity or
    // max size in bytes of the buffer.
    *sp = myStruct1;                // copy data from native into the Buffer
    myBuffer->Length = sizeof(*sp); // set the data length
    dataWriter->WriteBuffer(myBuffer);

}