如何在函数调用中正确使用CComPtr?

时间:2012-07-02 13:19:11

标签: c++ com directshow atl

我是COM和smartpointers的新手,我正在尝试将项目从原始指针转换为CComPtr,以避免内存管理的麻烦。我正在寻找关于如何在功能和范围方面正确使用CComPointers的一些建议。我的代码示例。

int  DisplayDeviceInformation(IEnumMoniker * pEnum, IMoniker * pMoniker)
{
    CComPtr<IPropertyBag> pPropBag = NULL;

    while (pEnum->Next(1, &pMoniker, NULL) == S_OK)
    {

        HRESULT hr = pMoniker->BindToStorage(0, 0, IID_PPV_ARGS(&pPropBag));
        if (FAILED(hr))
        {

        } 

        VARIANT var;
        VariantInit(&var);

        // Get description or friendly name.
        hr = pPropBag->Read(L"Description", &var, 0);
        if (FAILED(hr))
        {
            hr = pPropBag->Read(L"FriendlyName", &var, 0);
        }
        if (SUCCEEDED(hr))
        {
            printf("%S\n", var.bstrVal);
            VariantClear(&var); 
        }

        hr = pPropBag->Write(L"FriendlyName", &var);

        // WaveInID applies only to audio capture devices.
        hr = pPropBag->Read(L"WaveInID", &var, 0);
        if (SUCCEEDED(hr))
        {
            printf("WaveIn ID: %d\n", var.lVal);
            VariantClear(&var); 
        }

        hr = pPropBag->Read(L"DevicePath", &var, 0);
        if (SUCCEEDED(hr))
        {
            // The device path is not intended for display.
            printf("Device path: %S\n", var.bstrVal);
            VariantClear(&var); 
        }

    }
    return 0;
}

CComPtr<IMoniker> pMoniker = NULL;  
CComPtr<IMoniker> pMoniker2 = NULL;
    CComPtr<IEnumMoniker> pEnum = NULL;

    hr = EnumerateDevices(CLSID_VideoInputDeviceCategory, &pEnum);
//pEnum->Next(1, &pMoniker,&cFetched);

    if (SUCCEEDED(hr))
    {
        DisplayDeviceInformation(pEnum, pMoniker);     
    }
    pEnum = NULL;
    hr = EnumerateDevices(CLSID_AudioInputDeviceCategory, &pEnum);
    //pEnum->Next(1, &pMoniker2,&cFetched);
    if (SUCCEEDED(hr))
    {
        DisplayDeviceInformation(pEnum, pMoniker);
    }

基本上,第一个DisplayDeviceInformation(pEnum, pMoniker);给出了p == 0错误。但是,如果我取消注释pEnum->Next(1, &pMoniker,&cFetched);它的工作原理。使用原始指针我不必这样做,因为代码只是跳到下一个设备。任何建议或帮助都会让我感激不尽,提前谢谢!

1 个答案:

答案 0 :(得分:1)

CComPtr给你一个断言失败,你也可能遇到原始指针的问题。您只是没有预先警告,问题会在以后出现,例如作为参考泄密。

  1. 您似乎不需要全局范围内的IMoniker
  2. 在为枚举器
  3. 提供之前,您需要清除IMoniker指针

    见下文:

    int DisplayDeviceInformation(IEnumMoniker* pEnum, IMoniker** ppSelectedMoniker)
    {
        CComPtr<IMoniker> pMoniker;
        while (pEnum->Next(1, &pMoniker, NULL) == S_OK)
        {
            CComPtr<IPropertyBag> pPropBag; // You need it clear to start from for every moniker
            HRESULT hr = pMoniker->BindToStorage(0, 0, IID_PPV_ARGS(&pPropBag));
            // ...
            if(we should stop enumeration and we are good with current moniker)
            {
                //ATLASSERT(ppSelectedMoniker != NULL);
                *ppSelectedMoniker = pMoniker.Detach();
                return ...
            }
            // ...
            pMoniker.Release(); // You have to do this, so that next Next would accept empty CComPtr as an argument
        }
        return 0;
    }
    
    CComPtr<IEnumMoniker> pEnumVideoMoniker;
    CComPtr<IMoniker> pSelectedVideoMoniker;
    hr = EnumerateDevices(CLSID_VideoInputDeviceCategory, &pEnumVideoMoniker);
    if (SUCCEEDED(hr))
        DisplayDeviceInformation(pEnumVideoMoniker, &pSelectedVideoMoniker);     
    CComPtr<IEnumMoniker> pEnumAudioMoniker;
    CComPtr<IMoniker> pSelectedAudioMoniker;
    hr = EnumerateDevices(CLSID_AudioInputDeviceCategory, &pEnumAudioMoniker);
    if (SUCCEEDED(hr))
        DisplayDeviceInformation(pEnumAudioMoniker, &pSelectedAudioMoniker);