방법: CComPtr 및 CComQIPtr 인스턴스 만들기 및 사용
클래식 Windows 프로그래밍에서 라이브러리는 종종 COM 개체(보다 정확하게는 COM 서버)로 구현됩니다. 많은 Windows 운영 체제 구성 요소가 COM 서버로 구현되므로 많은 참가자가 이 형식의 라이브러리를 제공합니다. COM의 기본 사항에 대한 자세한 내용은 Component Object Model (COM)을 참조하세요.
COM(구성 요소 개체 모델) 개체를 인스턴스화할 때 소멸자에서 AddRef
및 Release
에 대한 호출을 사용하여 참조 계산을 수행하는 COM 스마트 포인터에 인터페이스 포인터를 저장합니다. ATL(액티브 템플릿 라이브러리) 또는 MFC 라이브러리를 사용하는 경우 CComPtr
스마트 포인터를 사용합니다. ATL 또는 MFC를 사용하지 않는 경우에는 _com_ptr_t
를 사용합니다. std::unique_ptr
에 해당하는 COM이 없기 때문에 단일 소유자 시나리오와 여러 소유자 시나리오 모두에 이러한 스마트 포인터를 사용합니다. CComPtr
과 ComQIPtr
둘 다 rvalue 참조가 있는 이동 작업을 지원합니다.
예: CComPtr
다음 예제에서는 CComPtr
을 사용하여 COM 개체를 인스턴스화하고 해당 인터페이스에 대한 포인터를 가져오는 방법을 보여 줍니다. CComPtr::CoCreateInstance
멤버 함수는 이름이 같은 Win32 함수 대신 COM 개체를 만드는 데 사용됩니다.
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은 COM 개체를 쿼리하여 추가 인터페이스를 검색할 수 있도록 보다 간단한 구문이 있는 CComQIPtr
을 제공합니다. 그러나 CComPtr
에서 수행할 수 있는 모든 작업을 수행하고 원시 COM 인터페이스 포인터와 의미 체계가 보다 일치하므로 CComQIPtr
을 사용하는 것이 좋습니다. CComPtr
를 사용하여 인터페이스를 쿼리하는 경우 out 매개 변수에 새 인터페이스 포인터가 배치됩니다. 호출에 실패한 경우 일반적인 COM 패턴인 HRESULT가 반환됩니다. CComQIPtr
을 사용하는 경우 반환 값은 포인터 자체이며, 호출에 실패한 경우 내부 HRESULT 반환 값에 액세스할 수 없습니다. 다음 두 줄은 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
은 COM 자동화 구성 요소에 대한 포인터를 저장하고 런타임에 바인딩을 사용하여 인터페이스에서 메서드를 호출할 수 있도록 하는 IDispatch 특수화를 제공합니다. CComDispatchDriver
는 암시적으로 CComQIPtr<IDispatch, &IIDIDispatch>
로 변환할 수 있는 CComPtr<IDispatch>
에 대한 typedef입니다. 따라서 이 세 가지 이름 중 하나가 코드에 표시되면 이는 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 문제를 단계적으로 폐지하고 이를 새로운 피드백 시스템으로 바꿀 예정입니다. 자세한 내용은 다음을 참조하세요.다음에 대한 사용자 의견 제출 및 보기