Можно ли вернуть CComPtr из функции?
Я пишу функцию, которая создает IMFSample и добавляет к нему буфер. Я хотел бы просто вернуть новый CComPtr в IMFSample, а не передавать указатель на указатель в параметрах. Это нормально делать это? Будет ли счетчик ссылок на образец IMFS правильным после выхода из функции? Я исследовал и не смог найти ни одного примера или обсуждения этого использования. Вот упрощенный пример функции:
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;
}
Спасибо.
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);
}