方法: CComPtr および CComQIPtr インスタンスを作成して使用する
従来の Windows プログラミングでは、ライブラリは、多くの場合、COM オブジェクトとして (厳密には COM サーバーとして) 実装されます。 多くの Windows オペレーティング システム コンポーネントは COM サーバーとして実装されており、多くの共同作成者からこの形式のライブラリが提供されています。 COM の詳細については、「 Component Object Model (COM)」を参照してください。
コンポーネント オブジェクト モデル (COM) オブジェクトをインスタンス化するときは、デストラクターの AddRef
と Release
の呼び出しを使用して参照のカウントを実行する COM スマート ポインターにインターフェイス ポインターを格納します。 Active Template Library (ATL) または Microsoft Foundation Class ライブラリ (MFC) を使用している場合は、 CComPtr
スマート ポインターを使用します。 ATL または MFC を使用していない場合は、 _com_ptr_t
を使用します。 COM には std::unique_ptr
に相当するものがないため、これらのスマート ポインターを単一所有者のシナリオと複数所有者のシナリオの両方に使用します。 CComPtr
と ComQIPtr
のどちらも、右辺値参照が含まれる移動操作をサポートしています。
例: CComPtr
次の例は、 CComPtr
を使用して COM オブジェクトをインスタンス化し、そのインターフェイスへのポインターを取得する方法を示しています。 COM オブジェクトを作成するために CComPtr::CoCreateInstance
メンバー関数が使用されている点に注意してください (同じ名前を持つ Win32 関数ではありません)。
void CComPtrDemo()
{
HRESULT hr = CoInitialize(NULL);
// Declare the smart pointer.
CComPtr<IGraphBuilder> pGraph;
// Use its member function CoCreateInstance to
// create the COM object and obtain the IGraphBuilder pointer.
hr = pGraph.CoCreateInstance(CLSID_FilterGraph);
if(FAILED(hr)){ /*... handle hr error*/ }
// Use the overloaded -> operator to call the interface methods.
hr = pGraph->RenderFile(L"C:\\Users\\Public\\Music\\Sample Music\\Sleep Away.mp3", NULL);
if(FAILED(hr)){ /*... handle hr error*/ }
// Declare a second smart pointer and use it to
// obtain another interface from the object.
CComPtr<IMediaControl> pControl;
hr = pGraph->QueryInterface(IID_PPV_ARGS(&pControl));
if(FAILED(hr)){ /*... handle hr error*/ }
// Obtain a third interface.
CComPtr<IMediaEvent> pEvent;
hr = pGraph->QueryInterface(IID_PPV_ARGS(&pEvent));
if(FAILED(hr)){ /*... handle hr error*/ }
// Use the second interface.
hr = pControl->Run();
if(FAILED(hr)){ /*... handle hr error*/ }
// Use the third interface.
long evCode = 0;
pEvent->WaitForCompletion(INFINITE, &evCode);
CoUninitialize();
// Let the smart pointers do all reference counting.
}
CComPtr
とその関連項目は ATL の一部であり、<atlcomcli.h> に定義されています。 _com_ptr_t
は <comip.h> で宣言されています。 コンパイラは、タイプ ライブラリのラッパー クラスを生成するときに _com_ptr_t
の特殊化を作成します。
例: CComQIPt
ATL では、よりシンプルな構文を持つ CComQIPtr
も提供されます。これを使用して COM オブジェクトに対するクエリを実行して、追加のインターフェイスを取得できます。 ただし、 CComPtr
で実行できることのすべてを実行可能であるうえ、未加工の COM インターフェイス ポインターとセマンティクス的により整合性の高い CComQIPtr
をお勧めします。 CComPtr
を使用してインターフェイスを照会すると、新しいインターフェイス ポインターが出力パラメーターに配置されます。 呼び出しが失敗した場合、HRESULT が返されます。これは、COM の一般的なパターンです。 CComQIPtr
の場合、戻り値はポインター自体です。呼び出しが失敗した場合、内部 HRESULT 戻り値にはアクセスできません。 次の 2 つの行から、 CComPtr
と CComQIPtr
におけるエラー処理機構の違いがわかります。
// CComPtr with error handling:
CComPtr<IMediaControl> pControl;
hr = pGraph->QueryInterface(IID_PPV_ARGS(&pControl));
if(FAILED(hr)){ /*... handle hr error*/ }
// CComQIPtr with error handling
CComQIPtr<IMediaEvent> pEvent = pControl;
if(!pEvent){ /*... handle NULL pointer error*/ }
// Use the second interface.
hr = pControl->Run();
if(FAILED(hr)){ /*... handle hr error*/ }
例: IDispatch
CComPtr
では、IDispatch の特殊化を提供して、COM オートメーション コンポーネントへのポインターを格納し、遅延バインディングを使用してインターフェイスのメソッドを呼び出すことができるようにしています。 CComDispatchDriver
は CComQIPtr<IDispatch, &IIDIDispatch>
の typedef であり、 CComPtr<IDispatch>
に暗黙的に変換可能です。 したがって、これらの 3 つの名前のいずれかがコードに使用されている場合、そのコードは CComPtr<IDispatch>
と同じです。 次の例に、 CComPtr<IDispatch>
を使用して Microsoft Word オブジェクト モデルへのポインターを取得する方法を示します。
void COMAutomationSmartPointerDemo()
{
CComPtr<IDispatch> pWord;
CComQIPtr<IDispatch, &IID_IDispatch> pqi = pWord;
CComDispatchDriver pDriver = pqi;
HRESULT hr;
_variant_t pOutVal;
CoInitialize(NULL);
hr = pWord.CoCreateInstance(L"Word.Application", NULL, CLSCTX_LOCAL_SERVER);
if(FAILED(hr)){ /*... handle hr error*/ }
// Make Word visible.
hr = pWord.PutPropertyByName(_bstr_t("Visible"), &_variant_t(1));
if(FAILED(hr)){ /*... handle hr error*/ }
// Get the Documents collection and store it in new CComPtr
hr = pWord.GetPropertyByName(_bstr_t("Documents"), &pOutVal);
if(FAILED(hr)){ /*... handle hr error*/ }
CComPtr<IDispatch> pDocuments = pOutVal.pdispVal;
// Use Documents to open a document
hr = pDocuments.Invoke1 (_bstr_t("Open"), &_variant_t("c:\\users\\public\\documents\\sometext.txt"),&pOutVal);
if(FAILED(hr)){ /*... handle hr error*/ }
CoUninitialize();
}
関連項目
フィードバック
https://aka.ms/ContentUserFeedback」を参照してください。
以下は間もなく提供いたします。2024 年を通じて、コンテンツのフィードバック メカニズムとして GitHub の issue を段階的に廃止し、新しいフィードバック システムに置き換えます。 詳細については、「フィードバックの送信と表示