【发布时间】:2018-08-21 09:15:32
【问题描述】:
我很难在 UWP 上的 C++/CX 代码中正确释放使用 SoftwareBitmap.LockBuffer() 方法锁定的 BitmapBuffer。
基本代码如下所示(它是来自 Microsoft 的 OpenCV 桥接示例,可用 here。
bool OpenCVHelper::GetPointerToPixelData(SoftwareBitmap^ bitmap, unsigned char** pPixelData, unsigned int* capacity)
{
BitmapBuffer^ bmpBuffer = bitmap->LockBuffer(BitmapBufferAccessMode::ReadWrite);
IMemoryBufferReference^ reference = bmpBuffer->CreateReference();
ComPtr<IMemoryBufferByteAccess> pBufferByteAccess;
if ((reinterpret_cast<IInspectable*>(reference)->QueryInterface(IID_PPV_ARGS(&pBufferByteAccess))) != S_OK)
{
return false;
}
if (pBufferByteAccess->GetBuffer(pPixelData, capacity) != S_OK)
{
return false;
}
return true;
}
然后使用此缓冲区 (pPixelData) 来初始化 cv:Mat 对象(浅拷贝)。并且永远不会被释放。
在同一个SoftwareBitmap 对象上连续调用LockBuffer() 引发异常:
Platform::AccessDeniedException ^ 在内存位置 0x00000002CEEFDCC0。 HRESULT:0x80070005 访问被拒绝。 WinRT 信息:位图共享锁被占用
如何正确释放这个缓冲区?尤其是在 C++/CX 中?
我试图保留引用以在不再需要时释放它。在 C++/CX 中,Dispose() 或 Close() 方法不可访问,编译器建议改为调用析构函数:
BitmapBuffer^ bmpBuffer = nullptr;
// ... get the buffer, use it
//((IDisposable^)bmpBuffer)->Dispose();
bmpBuffer->~BitmapBuffer();
但它不起作用(什么都不做)。正在调用析构函数,但对 LockBuffer() 的另一个调用引发了与以前相同的错误。
【问题讨论】:
-
我不确定你为什么需要明确释放
pPixelData缓冲区。但是如果你想这样做,你可以在它创建的地方释放它,并在这个函数OpenCVHelper::TryConvert在这一行创建它:unsigned char* pPixels = nullptr;。你可以像这样在pPixels = nullptr;之前释放它return true;。其实它是一个局部变量,在函数结束后会自动释放。 -
不是pPixelData,而是bmpBuffer(BitmapBuffer)。原因是要释放通过 LockBuffer() 方法获取的锁。否则它只能工作一次(我在文档中没有找到任何信息,一旦你使用 LockBuffer() 就无法释放它)。
标签: windows uwp windows-10-universal c++-cx windows-10-iot-core