C# のサンプルは多数ありますが、MSDN には C++ のコード スニペットがいくつかあります。私はそれをまとめましたが、うまくいくと思いますが、必要なすべての COM 参照を解放しているかどうかはわかりません。
3 に答える
あなたのコードは正しいです。 のIBufferByteAccessインターフェイスの参照カウントは、*bufferへの呼び出しによってインクリメントされます。その参照を解放するにはQueryInterface、 を 1 回呼び出す必要があります。Release
ただし、 を使用すると、これははるかにComPtr<T>簡単になりComPtr<T>ます。それらを呼び出すことができなくなります。代わりに、これらのメンバー関数の呼び出しをカプセル化して、混乱を招きにくくしています。これがどのように見えるかの例を次に示します。IUnknownAddRefReleaseQueryInterface
// 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*bufferAddRefRelease
これは私がこれまでに試したことです:
// 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()ヘルパー関数をインターフェイスで生成します。IBufferuint8_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()。