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