【问题标题】:how to copy bytes into a Windows::Storage::Streams::Buffer or IBuffer for ouput via Windows::Storage::Streams::DataWriter::WriteBuffer()如何将字节复制到 Windows::Storage::Streams::Buffer 或 Buffer 以通过 Windows::Storage::Streams::DataReader::WriteBuffer() 输出
【发布时间】:2018-09-25 16:51:27
【问题描述】:

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

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

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

要访问ReadBuffer() 返回的缓冲区,我正在使用一个函数,如果在Obtaining pointers to data buffers (C++/CX) 的网络上找到其源代码,则类似于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-&gt;WriteBuffer() 将其发送出去。

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

【问题讨论】:

    标签: uwp visual-studio-2017 c++-cx


    【解决方案1】:

    看来,可以用来获取指向Buffer内存区域的指针以将数据从Buffer复制到本机内存区域的相同函数也可用于获取指针,该指针可用于将数据复制到Buffer。有关IID_PPV_ARGS() 宏和ATL 智能指针类CComPtr 的信息,请参阅Obtaining pointers to data buffers (C++/CX).COM Coding Practices。参见QueryInterface: Navigating in an Object

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

    (ComPtr 是一个 WRL 智能指针。它自动化了 COM 的某些方面 否则很快就会变得乏味。它类似于 ATL 的 CComPtr,虽然 CComPtr 隐式执行的一些操作现在需要显式 代码,主要是因为那些隐式操作负责 代码中的许多错误是由并不真正了解如何编写的人编写的 CComPtr 有效。用新的ComPtr,一不明白怎么弄的 与运行时错误相比,works 更可能导致编译器错误。)

    还有ComPtr in the DirectXTK wiki

    Microsoft::WRL::ComPtr 是 COM 对象的 C++ 模板智能指针 在 Windows 运行时 (WinRT) C++ 编程中广泛使用。 它也适用于 Win32 桌面应用程序。它类似于 ATL 的 CComPtr 进行了一些有用的改进。 Microsoft::WRL:::ComPtr 在 Windows 8.x SDK 和 Windows 10 SDK,与 ATL 不同,它是 使用 Visual Studio 的 Express 版本时可用。它被使用 在 DirectX Tool Kit 中广泛使用以正确处理 COM 引用 计数维护。

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

    【讨论】:

    • 你也可以只用dataWriter-&gt;WriteBytes()写出字节,用Platform::Array保存数据。
    • @PeterTorr-MSFT 感谢您的建议。还有ReadBytes()吗?看起来有一个参数为 Byte 数组和最大大小或容量。我想我在使用以String 开头的示例时使用了Buffer 方法。我想Buffer 方法的好处是处理可变数据包大小,这是一个 UDP 客户端/服务器,Buffer 可能更容易。但是,我正在复制的原始应用程序为 UDP 网络流量使用了一个大缓冲区。
    • 是的,有一个ReadBytes() method on the DataReader。在 IDL 中,它表示为 {pointer, size} 一对参数,但它也应该投影为 Platform::Array
    • @PeterTorr-MSFT 感谢您提供链接,因为该页面上有一个指向Microsoft GitHub area with sample applications 的链接。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-12-24
    • 1970-01-01
    • 2020-03-18
    • 1970-01-01
    • 2021-05-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多