Freigeben über


Gewusst wie: Erstellen und Verwenden von CComPtr- und CComQIPtr-Instanzen

In Windows - klassisch Programmierung, werden Bibliotheken häufig als COM-Objekte implementiert (oder genau, COM-Server als). Viele Komponenten des Windows-Betriebssystems werden als COM-Server implementiert, und viele Mitwirkende stellen Bibliotheken in dieser Form. Informationen über die Grundlagen von COM, finden Sie unter Component Object Model (COM).

Wenn Sie ein (Component Object Model (COM)- Objekt instanziieren, speichern Sie den von Schnittstellenzeigern in einem COM-intelligentenZeiger, der die Verweiszählung ausgeführt, indem Aufrufe von AddRef und Release im Destruktor verwendet. Wenn Sie Active Template Library (ATL) oder der Microsoft Foundation Class-Bibliothek " (MFC-Bibliothek) verwenden, verwenden Sie den intelligenten Zeiger CComPtr. Wenn Sie nicht ATL oder MFC verwenden, verwenden Sie _com_ptr_t. Da keine COM-Entsprechung zu std::unique_ptr vorhanden sind, verwenden Sie diese intelligenten Zeiger für EinzelBesitzers- und MehrfachverbindungsstelleBesitzersszenarien. CComPtr und ComQIPtr unterstützen Verschiebungsvorgänge, die rvalue-Verweise haben.

Beispiel

Das folgende Beispiel zeigt, wie CComPtr verwendet, um ein COM-Objekt und Zeiger abzurufen den Schnittstellen zu instanziieren. Beachten Sie, dass die CComPtr::CoCreateInstance-Memberfunktion verwendet wird, um das COM-Objekt erstellen, statt der Win32-Funktion, die denselben Namen hat.

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 und die relativen sind Teil des ATL und werden in atlcomcli.h definiert. _com_ptr_t wird in comip.h deklariert. Der Compiler erstellt Spezialisierungen von _com_ptr_t, wenn er Wrapperklassen für Typbibliotheken generiert.

ATL stellt auch ein CComQIPtr, das eine einfachere Syntax zum Abfragen eines COM-Objekts, um eine zusätzliche Schnittstelle abgerufen hat. jedoch abgeraten CComPtr, da er aktiv wird, das CComQIPtr ausführen kann und Semantik mit unformatierten COM-Schnittstellenzeigern inern synchronisiert ist. Wenn Sie CComPtr verwenden, um für eine Schnittstelle abzufragen, wird der neue Schnittstellenzeiger in einen Out-Parameter eingefügt. Wenn der Aufruf fehlschlägt, wird ein HRESULT zurückgegeben, das das typische COM-Muster ist. Mit CComQIPtr ist der Rückgabewert der Zeiger selbst, und wenn der Aufruf fehlschlägt, kann auf den internen HRESULT-Rückgabewert nicht zugegriffen werden. Die folgenden beiden Zeilen zeigen, wie die Fehlerbehandlungsmechanismen in CComPtr und CComQIPtr unterscheiden.

// 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*/ }

CComPtr stellt eine Spezialisierung für IDispatch bereit, die es ermöglicht, Zeiger auf den COM-Automatisierungskomponenten zu speichern und die Methoden für die Schnittstelle aufzurufen, indem er als späte Bindung verwendet. CComDispatchDriver ist eine Typdefinition für CComQIPtr<IDispatch, &IIDIDispatch>, die CComPtr<IDispatch> implizit konvertiert werden kann. Wenn alle drei Namen im Code angezeigt wird, ist es für CComPtr<IDispatch>. Das folgende Beispiel zeigt, wie ein Zeiger dem Microsoft Word-Objektmodell erhält, indem es CComPtr<IDispatch> verwendet.

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();
}

Siehe auch

Konzepte

Intelligente Zeiger (Modern C++)