gpt4 book ai didi

c++ - 如果从函数返回指向指针 COM 对象的指针,是否需要 AddRef()?

转载 作者:行者123 更新时间:2023-11-30 04:46:54 24 4
gpt4 key购买 nike

下面是一个将资源图像从可执行文件加载到 ID2D1Bitmap 指针的函数。

我的问题是,我是否需要在 ID2D1Bitmap** ppBitmap 函数参数上调用 AddRef()

例如在函数的末尾我需要这个吗:

(*ppBitmap)->AddRef();

我看到互联网上的代码有时会进行此类调用,有时不会,但我无法理解何时有效,何时无效?

注意:对于最少的可编译代码,我提供了完整的功能,不包括错误检查实现。

#include <sdkddkver.h>
#include <Windows.h>
#include <wincodec.h> // WIC
#include <d2d1.h> // ID2D1Bitmap

//
// Loads resource Image from executable
// into ID2D1Bitmap* pointer
//
template<typename RenderType>
HRESULT LoadResourceImage(
IWICImagingFactory* pFactory,
PCTSTR szFilename,
PCTSTR szFileType,
RenderType* pRenderTarget,
ID2D1Bitmap** ppBitmap)
{
HRESULT hr = S_OK;
DWORD dwImageSize = 0;
HMODULE hModule = GetModuleHandle(nullptr);

HRSRC hResource = nullptr;
HGLOBAL hResourceData = nullptr;
void* pImageFile = nullptr;
IWICStream* pStream = nullptr;
IWICFormatConverter* pConverter = nullptr;
IWICBitmapFrameDecode* pFrameDecode = nullptr;
IWICBitmapDecoder* pDecoder = nullptr;

if (!hModule)
{
ShowError(__FILENAME__, __LINE__);
goto done;
}

hResource = FindResource(hModule, szFilename, szFileType);
if (!hResource)
{
ShowError(__FILENAME__, __LINE__);
goto done;
}

if (FAILED(hr = hResource ? S_OK : E_FAIL))
{
ShowError(__FILENAME__, __LINE__, hr);
goto done;
}

dwImageSize = SizeofResource(hModule, hResource);
if (!dwImageSize)
{
ShowError(__FILENAME__, __LINE__);
goto done;
}

if (FAILED(hr = dwImageSize ? S_OK : E_FAIL))
{
ShowError(__FILENAME__, __LINE__, hr);
goto done;
}

hResourceData = LoadResource(hModule, hResource);
if (!hResourceData)
{
ShowError(__FILENAME__, __LINE__);
goto done;
}

if (FAILED(hr = hResourceData ? S_OK : E_FAIL))
{
ShowError(__FILENAME__, __LINE__, hr);
goto done;
}

pImageFile = LockResource(hResourceData);
if (!pImageFile)
{
ShowError(__FILENAME__, __LINE__);
goto done;
}

if (FAILED(hr = pImageFile ? S_OK : E_FAIL))
{
ShowError(__FILENAME__, __LINE__, hr);
goto done;
}

if (FAILED(hr = pFactory->CreateStream(&pStream)))
{
ShowError(__FILENAME__, __LINE__, hr);
goto done;
}

hr = pStream->InitializeFromMemory(
reinterpret_cast<BYTE*>(pImageFile), dwImageSize);

if (FAILED(hr))
{
ShowError(__FILENAME__, __LINE__, hr);
goto done;
}

hr = pFactory->CreateDecoderFromStream(
pStream,
nullptr,
WICDecodeMetadataCacheOnDemand,
&pDecoder);

if (FAILED(hr))
{
ShowError(__FILENAME__, __LINE__, hr);
goto done;
}

if (FAILED(hr = pDecoder->GetFrame(0, &pFrameDecode)))
{
ShowError(__FILENAME__, __LINE__, hr);
goto done;
}

if (FAILED(hr = pFactory->CreateFormatConverter(&pConverter)))
{
ShowError(__FILENAME__, __LINE__, hr);
goto done;
}

hr = pConverter->Initialize(
pFrameDecode,
GUID_WICPixelFormat32bppPRGBA,
WICBitmapDitherTypeNone,
nullptr,
0.f,
WICBitmapPaletteTypeCustom);

if (FAILED(hr))
{
ShowError(__FILENAME__, __LINE__, hr);
goto done;
}

hr = pRenderTarget->CreateBitmapFromWicBitmap(
pConverter,
0,
ppBitmap);

if (FAILED(hr))
{
ShowError(__FILENAME__, __LINE__, hr);
goto done;
}

done:
SafeRelease(&pFrameDecode);
SafeRelease(&pDecoder);
SafeRelease(&pConverter);
SafeRelease(&pStream);

return hr;
}

最佳答案

hr = pRenderTarget->CreateBitmapFromWicBitmap(
pConverter,
0,
ppBitmap);

成功调用上面的 CreateBitmapFromWicBitmap 方法返回的 ID2D1Bitmap 对象,已经设置了正确的引用计数。因此,您不应该对其调用 AddRef

当您完成对象时,您只需在 ID2D1Bitmap* COM 接口(interface)指针上调用 Release

相反,如果您在返回的指针上再次显式调用 AddRef,您将需要一个适当的 additional 匹配 Release 调用,否则返回的对象不会自行释放。

请注意,由于我们讨论的是 C++ 代码(而非 C 代码),您可以使用智能指针(如 ATL::CComPtr)简化所有这些 COM 接口(interface)指针生命周期管理代码,而不是指向 COM 接口(interface)的原始指针。

CComPtr自动在包装的原始 COM 接口(interface)指针(例如,在作用域结束时,Release 将由 ~CComPtr 析构函数调用),因此您不必关注这些 COM 对象生命周期细节。此外,同样在发生异常的情况下,Release 也会自动调用,因此您不会在抛出异常时泄漏 COM 对象。

关于c++ - 如果从函数返回指向指针 COM 对象的指针,是否需要 AddRef()?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56462922/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com