Procedura: Creare e utilizzare le istanze di CComQIPtr e di CComPtr
Nella programmazione Windows classico, librerie spesso vengono implementate come oggetti COM (o più precisamente, come server COM).Molti componenti del sistema operativo Windows sono implementati come server COM e molti collaboratori forniscono le librerie in questo modulo.Per informazioni sulle nozioni fondamentali di COM, vedere Component Object Model (COM).
Quando si crea un'istanza di un oggetto Component Object Model (COM), memorizzare il puntatore a interfaccia in un puntatore COM intelligente, che esegue utilizzando chiamate di conteggio dei riferimenti AddRef e Release nel distruttore.Se si utilizza la libreria ATL (Active Template) o MFC Microsoft Foundation Class Library (), quindi utilizzare il CComPtr puntatore intelligente.Se non si utilizza MFC o ATL, utilizzare _com_ptr_t.Poiché nessun COM è equivalente a std::unique_ptr, utilizzare questi puntatori intelligenti per singolo proprietario e proprietario di più scenari.Entrambi CComPtr e ComQIPtr supporto spostare le operazioni che hanno riferimenti rvalue.
Esempio
Nell'esempio riportato di seguito viene illustrato come utilizzare CComPtr per creare un'istanza di un oggetto COM e ottenere i puntatori a interfacce.Si noti che il CComPtr::CoCreateInstance membro funzione viene utilizzata per creare l'oggetto COM, anziché la funzione Win32 che ha lo stesso nome.
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.
}
CComPtre relativi componenti fanno parte di ATL e vengono definiti in atlcomcli.h._com_ptr_tviene dichiarato in comip.h.Il compilatore crea specializzazioni di _com_ptr_t quando genera le classi wrapper per le librerie dei tipi.
ATL fornisce inoltre CComQIPtr, che ha una sintassi più semplice per eseguire query in un oggetto COM per recuperare un'interfaccia aggiuntiva.Si consiglia tuttavia di CComPtr perché tutto ciò che CComQIPtr possibile eseguire ed è semanticamente più coerenti con i puntatori di interfaccia COM non elaborati.Se si utilizza un CComPtr per eseguire una query per un'interfaccia, il nuovo puntatore di interfaccia viene inserito in un parametro out.Se la chiamata ha esito negativo, viene restituito un HRESULT che rappresenta il modello COM tipico.Con CComQIPtr, il valore restituito è il puntatore del mouse se stesso e se la chiamata ha esito negativo, il valore restituito HRESULT interno non saranno accessibili.I seguenti due righe come meccanismi di gestione degli errori CComPtr e CComQIPtr sono diversi.
// 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*/ }
CComPtrfornisce una specializzazione per IDispatch che consente di archiviare i puntatori ai componenti di automazione COM e richiamare i metodi sull'interfaccia utilizzando l'associazione tardiva.CComDispatchDriverè un typedef per CComQIPtr<IDispatch, &IIDIDispatch>, che è implicitamente convertibile in CComPtr<IDispatch>.Di conseguenza, quando uno di questi tre nomi viene visualizzato nel codice, è equivalente a CComPtr<IDispatch>.Nell'esempio riportato di seguito viene illustrato come ottenere un puntatore al modello a oggetti Microsoft Word utilizzando un 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();
}