如何使用C++访问WriteableBitmap.PixelBuffer像素?

Fil*_*kun 4 com windows-runtime c++-cx winrt-xaml

C#有很多样本,但MSDN上的C++只有一些代码片段.我把它放在一起,我认为它会工作,但我不确定我是否发布了我必须的所有COM引用.

Jam*_*lis 5

您的代码是正确的 - IBufferByteAccess接口上的引用计数*buffer通过调用递增QueryInterface,您必须调用Release一次以释放该引用.

但是,如果你使用ComPtr<T>,这变得简单多了-有ComPtr<T>,你不能调用任何的三名成员IUnknown(AddRef,Release,和QueryInterface); 它阻止你打电话给他们.相反,它以一种难以搞砸的方式封装对这些成员函数的调用.这是一个如何看起来的例子:

// Get the buffer from the WriteableBitmap:
IBuffer^ buffer = bitmap->PixelBuffer;

// Convert from C++/CX to the ABI IInspectable*:
ComPtr<IInspectable> bufferInspectable(AsInspectable(buffer));

// Get the IBufferByteAccess interface:
ComPtr<IBufferByteAccess> bufferBytes;
ThrowIfFailed(bufferInspectable.As(&bufferBytes));

// Use it:
byte* pixels(nullptr);
ThrowIfFailed(bufferBytes->Buffer(&pixels));
Run Code Online (Sandbox Code Playgroud)

bufferInspectable.As(&bufferBytes)执行安全的调用QueryInterface:它从类型中计算IID bufferBytes,执行QueryInterface,并将结果指针附加到bufferBytes.当bufferBytes超出范围时,它会自动调用Release.代码与您的代码具有相同的效果,但没有容易出错的显式资源管理.

该示例使用以下两个实用程序,这有助于保持代码清洁:

auto AsInspectable(Object^ const object) -> Microsoft::WRL::ComPtr<IInspectable>
{
    return reinterpret_cast<IInspectable*>(object);
}

auto ThrowIfFailed(HRESULT const hr) -> void
{
    if (FAILED(hr))
        throw Platform::Exception::CreateException(hr);
}
Run Code Online (Sandbox Code Playgroud)

细心的读者会发现,因为这个代码使用ComPtrIInspectable*我们从拿到buffer,这段代码实际上执行附加AddRef/ Release比原来的代码.我认为这种影响性能的可能性很小,最好从易于验证的代码开始,然后在理解热点后优化性能.