Как получить доступ к WriteableBitmap.Пиксельбуфер пикселей с C++?



Существует множество примеров для C#, но только некоторые фрагменты кода для C++ на MSDN. Я собрал его вместе, и я думаю, что он будет работать, но я не уверен, что я выпускаю все ссылки COM, которые у меня есть.

369   2  

2 ответов:

Ваш код верен-количество ссылок на 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));

Вызов 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);
}

Наблюдательные читатели заметим, что поскольку этот код использует ComPtr для IInspectable*, который мы получаем из buffer, этот код фактически выполняет дополнительный AddRef/Release по сравнению с исходным кодом. Я бы сказал, что вероятность такого влияния на производительность минимальна, и лучше всего начать с кода, который легко проверить как правильный, а затем оптимизировать для производительности, как только будут поняты горячие точки.

Вот что я пытался сделать до сих пор:

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

Comments

    Ничего не найдено.