5

C# のサンプルは多数ありますが、MSDN には C++ のコード スニペットがいくつかあります。私はそれをまとめましたが、うまくいくと思いますが、必要なすべての COM 参照を解放しているかどうかはわかりません。

4

3 に答える 3

5

あなたのコードは正しいです。 の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、結果のポインタを にアタッチしますbufferBytesbufferBytes範囲外になると、自動的に が呼び出されます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

于 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++/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()

于 2021-05-01T07:29:34.647 に答える