C# のサンプルは多数ありますが、MSDN には C++ のコード スニペットがいくつかあります。私はそれをまとめましたが、うまくいくと思いますが、必要なすべての COM 参照を解放しているかどうかはわかりません。
3 に答える
あなたのコードは正しいです。 のIBufferByteAccess
インターフェイスの参照カウントは、*buffer
への呼び出しによってインクリメントされます。その参照を解放するにはQueryInterface
、 を 1 回呼び出す必要があります。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
。コードはあなたのものと同じ効果がありますが、エラーが発生しやすい明示的なリソース管理はありません。
この例では、コードをクリーンに保つのに役立つ次の 2 つのユーティリティを使用しています。
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();
(C++/CX の代わりに) C ++/WinRTを使用する場合、より便利な (そしてより危険な) 代替手段があります。言語プロジェクションは、メモリ バッファーに a を返すdata()
ヘルパー関数をインターフェイスで生成します。IBuffer
uint8_t*
bitmap
タイプがWriteableBitmapであると仮定すると、コードは次のように切り詰めることができます。
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()
。