首页 > 解决方案 > C++/WinRT 运行时组件返回大数组

问题描述

我正在尝试使用 C++/WinRT 编写一个 Windows 运行时组件,该组件将从 C# 用于统一程序。我是全新的 C++,但花了很长时间,我设法通过返回 Windows.Graphics.Imaging.SoftwareBitmap通过 windows API 来的对象来使代码工作。但是返回SoftwareBitmap很慢,我将代码更改为返回com_array

返回com_array确实可以显着加快速度,但现在我经常遇到访问冲突读取位置 xxxxx错误。作为在 C++ 方面经验有限的人,我正在努力正确地做到这一点。下面是我的代码的简化版本。为简单起见,我删除了大部分代码。

1.FrameData

#FrameData.idl

runtimeclass FrameData
    {
        RMFrameData();
        BYTE[] imageArray;
    }

#FrameData.h
struct FrameData : FrameData <RMFrameData>
{
    RMFrameData() = default;
    ~RMFrameData();

    com_array<uint8_t>& imageArray();
    void imageArray(array_view<uint8_t const> value);

private:
    com_array<uint8_t> m_imageArray{};
};

#FrameData.cpp
 RMFrameData::~RMFrameData()
 {
     m_imageArray.clear();
 }
com_array<uint8_t>& RMFrameData::imageArray()
{
    return m_imageArray;
}
void RMFrameData::imageArray(array_view<uint8_t const> value)
{
    m_imageArray = winrt::com_array<BYTE>(std::move_iterator(value.begin()), std::move_iterator(value.end()));
}

使用 FrameData 发送它的方法如下。

void PVProcessor::OnFrameArrived(const MediaFrameReader& sender, const MediaFrameArrivedEventArgs& args)
    {

        if (MediaFrameReference frame = sender.TryAcquireLatestFrame())
        {
            auto frame_data = winrt::make_self<winrt::HL2CV_WRT::implementation::RMFrameData>();

            if (frame != nullptr && frame.VideoMediaFrame() != nullptr) {
    
                uint32_t pixelBufferDataLength = 0;
                uint8_t* pixelBufferData;
                SoftwareBitmap bitmap = SoftwareBitmap::Convert(frame.VideoMediaFrame().SoftwareBitmap(), BitmapPixelFormat::Bgra8);
                if (bitmap != nullptr) {
                    BitmapBuffer bitmapBuffer = bitmap.LockBuffer(BitmapBufferAccessMode::Read);

                    auto spMemoryBufferByteAccess{ bitmapBuffer.CreateReference().as<::Windows::Foundation::IMemoryBufferByteAccess>() };
                    winrt::check_hresult(spMemoryBufferByteAccess->GetBuffer(&pixelBufferData, &pixelBufferDataLength));

                    std::vector<BYTE> pixelVectorData{};
                    pixelVectorData.insert(pixelVectorData.end(), std::make_move_iterator(pixelBufferData), std::make_move_iterator(pixelBufferData + pixelBufferDataLength));
                    frame_data->imageArray(pixelVectorData); //set com_array here.
                    bitmap.Close();
                }

            }
            frame.Close();
            m_frame_data_available(*this, *frame_data);
        }
    }

使用 C# 中的 FrameData 的方法如下。

void OneFrameAvailable(object sender, RMFrameData e){
  
        var array = e.imageArray;
        
 /*
    use array data here
 */
    }

代码var array = e.imageArray;抛出错误访问冲突读取位置 xxxx

我的问题是

  1. 如何m_imageArrayFrameData.h中正确初始化。
  2. m_imageArray在 C# 中使用析构函数后是否正确清理?
  3. 使用帧数据后是否需要从 C# 代码中显式调用析构函数?
  4. 我像java一样编写C++代码,所以我相信有很多错误。请让我知道其他需要更正的事情。
  5. 目标是能够访问softwarebitmap的数据,c#而无需一路复制。如何?谢谢。

标签: c++windows-runtimec++-winrt

解决方案


推荐阅读