Аргумент функции двойного указателя и CComPtr - PullRequest
3 голосов
/ 07 ноября 2011

Я не уверен в этом способе использования CComPtr внутри функции, аргумент которой выражен в виде двойного указателя:

HRESULT D3DPresentEngine::CreateD3DSample(
    IDirect3DSwapChain9 *pSwapChain, 
    IMFSample **ppVideoSample
    )
{
    // Caller holds the object lock.

    D3DCOLOR clrBlack = D3DCOLOR_ARGB(0xFF, 0x00, 0x00, 0x00);

    CComPtr< IDirect3DSurface9 > pSurface;
    CComPtr< IMFSample > pSample;

    // Get the back buffer surface.
    ReturnIfFail( pSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &pSurface ) );

    // Fill it with black.
    ReturnIfFail( m_pDevice->ColorFill(pSurface, NULL, clrBlack));

    // Create the sample.
    ReturnIfFail( MFCreateVideoSampleFromSurface(pSurface, &pSample));

    // Return the pointer to the caller.
    *ppVideoSample = pSample;
    (*ppVideoSample)->AddRef();

    return S_OK;
}

У меня есть сомнения по поводу последнего вызова присваивания + AddRef.

Они в порядке для вас?

Заранее спасибо

Ответы [ 3 ]

3 голосов
/ 07 ноября 2011

Более идиоматическая версия будет

// Transfer the pointer to our caller.
*ppVideoSample = pSample.Detach();

Если вы хотите копировать семантику, а не передавать, вы должны использовать

pSample.CopyTo(ppVideoSample);
3 голосов
/ 07 ноября 2011

Это нормально, но можно упростить:

HRESULT D3DPresentEngine::CreateD3DSample(
    IDirect3DSwapChain9 *pSwapChain, 
    IMFSample **ppVideoSample
    )
{
    // Caller holds the object lock.

    D3DCOLOR clrBlack = D3DCOLOR_ARGB(0xFF, 0x00, 0x00, 0x00);

    CComPtr< IDirect3DSurface9 > pSurface;

    // Get the back buffer surface.
    ReturnIfFail( pSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &pSurface ) );

    // Fill it with black.
    ReturnIfFail( m_pDevice->ColorFill(pSurface, NULL, clrBlack));

    // Create the sample.
    ReturnIfFail( MFCreateVideoSampleFromSurface(pSurface, ppVideoSample));

    return S_OK;
}

В вашем коде необходимо AddRef, потому что pSample будет Release, когда выйдет из области видимости.

0 голосов
/ 07 ноября 2011

Назначение и разыменование для AddRef() являются правильными.

Когда вызывается MFCreateVideoSampleFromSurface(), вторым аргументом для него является место, где должен храниться указатель на интерфейс. Вы используете &pSample, чтобы получить адрес для передачи в функцию. Это соответствует типу IMFSample **. Обратите внимание, что оператор & для CComPtr<> через CComPtrBase<> возвращает правильный тип.

CComPtrBase :: & operator @ MSDN

ppVideoSample также имеет тип IMFSample **, что требует от оператора * разыменования указателя интерфейса. Это дает указатель типа IMFSample *, который можно вызвать с помощью оператора -> для доступа к AddRef() и другим функциям интерфейса.

...