【问题标题】:Getting an array of bytes out of Windows::Storage::Streams::IBuffer从 Windows::Storage::Streams::IBuffer 中获取字节数组
【发布时间】:2012-08-07 20:43:54
【问题描述】:

我有一个实现接口Windows::Storage::Streams::IBuffer 的对象,我想从中获取一个字节数组,但是在查看文档时,这个接口看起来毫无用处,并且文档没有提供任何对任何接口的引用可以与此接口结合以实现我的目的的其他类。到目前为止,我在谷歌上发现的只是对 .Net 类WindowsRuntimeBufferExtensions 的引用,但我使用的是 C++,所以这也是一条死胡同。

有人可以提示如何在 C++ 中从 Windows::Storage::Streams::IBuffer 获取字节数组吗?

【问题讨论】:

    标签: c++ stream windows-8 windows-runtime visual-studio-2012


    【解决方案1】:

    您可以通过奇异的 COM 强制转换来使用 IBufferByteAccess:

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

    http://cm-bloggers.blogspot.fi/2012/09/accessing-image-pixel-data-in-ccx.html复制的代码示例

    【讨论】:

    • 我改变了我的实现,现在我正在使用这种方法,因为它提高了我的应用程序的性能。谢谢。
    【解决方案2】:

    也检查这个方法:

    IBuffer -> Platform::Array
    CryptographicBuffer.CopyToByteArray

    Platform::Array -> IBuffer
    CryptographicBuffer.CreateFromByteArray

    附带说明,如果您想从简单的 C++ 数组创建 Platform::Array,您可以使用 Platform::ArrayReference,例如:

    char* c = "sdsd";
    Platform::ArrayReference<unsigned char> arraywrapper((unsigned char*) c, sizeof(c));
    

    【讨论】:

    • 谢谢这让我头疼了!,作为参考,ArrayReference 在 Platform 命名空间中。
    • 警告:sizeof(c) 将产生指针的大小,而不是字符串的长度。
    【解决方案3】:

    这是一个 C++/CX 版本:

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

    欲了解更多信息,请参阅Array and WriteOnlyArray (C++/CX)

    【讨论】:

      【解决方案4】:

      如前所述,命名空间System::Runtime::InteropServices::WindowsRuntime 中的WindowsRuntimeBufferExtensions 仅适用于.Net 应用程序,不适用于本机C++ 应用程序。

      一个可能的解决方案是使用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];
      
          (...)
      }
      

      【讨论】:

        【解决方案5】:

        这应该适用于 WinRT 扩展:

        // 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
        

        【讨论】:

        • 几乎没有关于这个类 Platform::ArrayReference 的文档,请问您在哪里找到这些信息?
        • 这是一个来自 MSDN msdn.microsoft.com/en-us/library/hh700131.aspx 的示例“使用 ArrayReference 避免复制数据”
        【解决方案6】:

        由于这个问题被标记为,这里有一个使用C++/WinRT 的解决方案。它在本质上与 this answer 的作用相同,但更易于访问。 IBuffer 投影上的(未记录的)data() 助手完成了所有繁重的工作:

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

        遗憾的是(还没有)官方文档,我只是在 WritableBitmap.PixelBuffer 属性的示例代码中偶然发现了这一点(请确保从语言下拉列表中选择 "C++/WinRT"在右上角)。

        当从语言下拉列表中选择 "C++/CX" 时,该文档条目也提供了相同的解决方案(查询 IBufferByteAccess 接口)。

        【讨论】:

          【解决方案7】:

          Use the extension method like a static method:

          IBuffer *buffer;
          array<unsigned char>^ result= System::Runtime::InteropServices::WindowsRuntime::WindowsRuntimeBufferExtensions::ToArray(buffer);
          

          【讨论】:

          • @user787913,一开始我也很困惑。
          • @MSN WindowsRuntimeBufferExtensions 是 .Net 框架中的一个类,它不能在本机 C++ 应用程序中使用
          猜你喜欢
          • 2018-09-25
          • 2014-05-17
          • 2016-01-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多