【问题标题】:Is it ok to return a CComPtr from a function?从函数返回 CComPtr 可以吗?
【发布时间】:2018-09-25 16:20:21
【问题描述】:

我正在编写一个创建 IMFSample 并向其添加缓冲区的函数。我只想将新的 CComPtr 返回到 IMFSample 而不是将指针传递给参数中的指针。这样做可以吗?当函数退出时,对 IMFSample 的引用计数是否正确?我进行了研究,但找不到任何有关此用法的示例或讨论。下面是一个简化的函数示例:

CComPtr<IMFSample> getSample() {
    HRESULT hr = S_OK;
    CComPtr<IMFSample> pSample = NULL;

    hr = MFCreateSample(&pSample);
    if (hr != S_OK) {
        // pSample should be released at exception.
        throw "MFCreateSample failed";
    }

    // ...Create buffer, Add buffer, etc...

    return pSample;
}

在这里,我添加了一个较长的版本,以帮助展示它如何通过使用异常来简化我的错误处理。我的程序的其余部分是使用异常构造的,因此我试图隔离“COM”部分,以尽可能使它们与其余部分更好地适应。

void decodeLoop() {
    CComPtr<IMFSample> pSample;

    while (noError) {
        try {
            pSample = getNALSample(decoderPkt, MAX_SIZE);
            processSample(pSample);
            pSample = NULL;
            ...
        }
        catch (MyException& e) {
            ...
        }
    }
}

CComPtr<IMFSample> getNALSample(DecoderPkt* decoderPkt, DWORD maxBuffSize) {
    HRESULT hr = S_OK;
    CComPtr<IMFSample> pSample = nullptr;
    CComPtr<IMFMediaBuffer> pMediaBuffer = nullptr;
    byte *pBuffer = nullptr;

    // MFCreate Sample
    hr = MFCreateSample(&pSample);
    if (hr != S_OK) 
        throw MyException(hr, "getNALSample::MFCreateSample failed");

    // Get buffer
    hr = MFCreateMemoryBuffer(maxBuffSize, &pMediaBuffer);
    if (hr != S_OK) 
        throw MyException(hr, "getNALSample::MFCreateMemoryBuffer failed");

    // Set up buffer pointer
    hr = pMediaBuffer->Lock(&pBuffer, nullptr, nullptr);
    if (hr != S_OK) 
        throw MyException(hr, "getNALSample::pMediaBuffer->Lock failed");

    // Build NAL from decoder que
    hr = pMediaBuffer->SetCurrentLength(buildNAL(pBuffer, decoderPkt));
    if (hr != S_OK) 
        throw MyException(hr, "getNALSample::pMediaBuffer->SetCurrentLength failed");

    hr = pMediaBuffer->Unlock();
    if (hr != S_OK) 
        throw MyException(hr, "getNALSample::pMediaBuffer->Unlock failed");

    // Add buffer to sample
    hr = pSample->AddBuffer(pMediaBuffer);
    if (hr != S_OK) 
        throw MyException(hr, "getNALSample::pSample->AddBuffer failed");

    return pSample;
}

谢谢。

【问题讨论】:

  • 我觉得不错。
  • 会好的

标签: com atl ms-media-foundation


【解决方案1】:

效果很好。

你看不到这种用法的原因是,它的设计方式看起来像是一个真正的“私有”方法。

另外,它会抛出而不是返回 HRESULT。就个人而言,我总是更喜欢返回 HRESULT 而不是投掷(即使你随身携带 ComPtr),因为它更容易处理。

这是一种(我承认更复杂)的方法,看起来更像“COM”(或者如果你愿意的话,也可以更像“Microsoft”):

HRESULT GetSample(REFIID riid, void**ppv) // you can add other parameters (in front, and leave riid and ppv last)
{
  HRESULT hr = S_OK;
  CComPtr<IMFSample> pSample;

  hr = MFCreateSample(&pSample);
  if (hr != S_OK) return hr; // or if (FAILED(hr) ? depends if you handle S_FALSE an other non error cases

  // ...Create buffer, Add buffer, etc...

  return pSample->QueryInterface(riid, ppv);
}

【讨论】:

  • 感谢您的回答。我已经编辑了我的原始帖子,以展示我正在尝试做的事情的更大图景。基本上我的目标是尽可能地将“COM”部分隔离到使用异常而不是错误返回的函数中,以便最好地匹配我程序其余部分的错误处理结构。
猜你喜欢
  • 2011-05-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多