Jak: tworzenie i używanie instancje CComQIPtr i CComPtr
Klasyczny Windows programowania, biblioteki często są implementowane jako obiekty COM (lub dokładniej, jako serwery COM).Wiele składników systemu operacyjnego Windows są implementowane jako serwery COM i wielu współautorom zapewniają biblioteki w tym formularzu.Informacje podstawowe COM, zobacz Component Object Model (COM).
Kiedy można utworzyć wystąpienia obiektu modelu COM (Component Object), przechowywać wskaźnika interfejsu w wskaźnik inteligentne COM, który wykonuje Zliczanie przy użyciu wywołania odwołań AddRef i Release w destruktor.Jeśli używasz Active Template Library (ATL) lub Microsoft Foundation klasy biblioteki (MFC), użyj CComPtr wskaźnik inteligentne.Jeśli nie używasz ATL i MFC, użyj _com_ptr_t.Ponieważ nie COM jest równoważne z std::unique_ptr, użyj tych Sprytne wskaźniki dla pojedynczego właściciela i właściciela wielu scenariuszy.Obie CComPtr i ComQIPtr wsparcia przenieść operacje, które mają odwołania rvalue.
Przykład
Poniższy przykład pokazuje, jak używać CComPtr do tworzenia wystąpienia obiektu COM i uzyskania wskaźników do swoich interfejsach.Warto zauważyć, że CComPtr::CoCreateInstance Członkowskich funkcji jest używany do tworzenia obiektu COM, zamiast funkcji Win32, który ma taką samą nazwę.
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.
}
CComPtri jego krewni są częścią ATL i są zdefiniowane w atlcomcli.h._com_ptr_tjest zadeklarowany w comip.h.Kompilator tworzy specjalizacji, z _com_ptr_t Kiedy generuje klas otoki biblioteki typów.
Zapewnia także ATL CComQIPtr, który ma prostsze składnię kwerenda obiektu COM, aby pobrać dodatkowe interfejsu.Jednak zaleca się CComPtr , ponieważ nie wszystkie elementy, CComQIPtr można wykonać i jest semantycznie bardziej spójne z surowego wskaźników interfejsów COM.Jeśli korzystasz z CComPtr dla interfejsu kwerendy nowego wskaźnika interfejsu jest umieszczana w parametrze wyjściowym.Jeśli połączenie nie powiedzie się, HRESULT jest zwracany, co jest typowe deseń COM.Z CComQIPtr, zwracana jest wartość wskaźnika, sam i jeśli połączenie nie powiedzie się, nie uzyskać dostępu do wewnętrznego wartości zwracanej wartości HRESULT.Następujące dwie linie Pokaż jak błąd, mechanizmów obsługi CComPtr i CComQIPtr różnią się.
// 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*/ }
CComPtrzapewnia specjalizacji IDispatch, która pozwala przechowywać wskaźniki składników automatyzacji COM i wywoływać metody w interfejsie korzystając z późnym wiązaniem.CComDispatchDriverjest typedef dla CComQIPtr<IDispatch, &IIDIDispatch>, który jest niejawnie do CComPtr<IDispatch>.W związku z tym, gdy dowolne z tych trzech nazw pojawi się w kodzie, jest równoważne z CComPtr<IDispatch>.Poniższy przykład pokazuje, jak uzyskać wskaźnik do modelu obiektu programu Microsoft Word przy użyciu CComPtr<IDispatch>.
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();
}
Zobacz też
Koncepcje
Inteligentne kursory (Podręcznik programowania C++ nowoczesny)