5

C# 的示例很多,但 MSDN 上只有一些 C++ 的代码片段。我已经把它放在一起,我认为它会起作用,但我不确定我是否要发布我必须发布的所有 COM 引用。

4

3 回答 3

5

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

但是,如果您使用ComPtr<T>,这将变得更加简单——使用ComPtr<T>,您不能调用IUnknown( AddRefReleaseQueryInterface) 的三个成员中的任何一个;它会阻止你打电话给他们。相反,它以一种难以搞砸的方式封装对这些成员函数的调用。这是一个外观示例:

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

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

细心的读者会注意到,由于这段代码使用 aComPtr表示IInspectable*我们从中得到的,因此与原始代码相比buffer,这段代码实际上执行了一个额外的AddRef/ 。Release我认为这种影响性能的可能性很小,最好从易于验证是否正确的代码开始,然后在了解热点后优化性能。

于 2012-12-05T03:25:32.807 回答
0

这是我到目前为止所尝试的:

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

// Get access to the base COM interface of the buffer (IUnknown)
IUnknown* pUnk = reinterpret_cast<IUnknown*>(buffer);

// Use IUnknown to get the IBufferByteAccess interface of the buffer to get access to the bytes
// This requires #include <Robuffer.h>
IBufferByteAccess* pBufferByteAccess = nullptr;
HRESULT hr = pUnk->QueryInterface(IID_PPV_ARGS(&pBufferByteAccess));

if (FAILED(hr))
{
    throw Platform::Exception::CreateException(hr);
}

// Get the pointer to the bytes of the buffer
byte *pixels = nullptr;
pBufferByteAccess->Buffer(&pixels);

// *** Do the work on the bytes here ***

// Release reference to IBufferByteAccess created by QueryInterface.
// Perhaps this might be done before doing more work with the pixels buffer,
// but it's possible that without it - the buffer might get released or moved
// by the time you are done using it.
pBufferByteAccess->Release();
于 2012-12-04T17:41:16.563 回答
0

当使用C++/WinRT(而不是 C++/CX)时,有一个更方便(也更危险)的替代方案。语言投影在将 a 返回到内存缓冲区的接口data()上生成一个辅助函数。IBufferuint8_t*

假设它bitmapWriteableBitmap类型,则可以将代码缩减为:

uint8_t* pixels{ bitmap.PixelBuffer().data() };

// *** Do the work on the bytes here ***

// No cleanup required; it has already been dealt with inside data()'s implementation

在代码pixels中是指向由bitmap实例控制的数据的原始指针。因此,它仅在bitmap活着的情况下才有效,但代码中没有任何内容可以帮助编译器(或阅读器)跟踪该依赖关系。

作为参考,文档中有一个示例说明WriteableBitmap::PixelBuffer了(否则未记录的)辅助函数的使用data()

于 2021-05-01T07:29:34.647 回答