COM智能指针ComPtr的介绍以及使用

ComPtr介绍

ComPtr是为COM而设计的智能指针。它支持WindowsRT,也支持传统Win32。相比ATL里的CComPtr类,它有了一些提升。ComPtr会自动维护基础接口指针的引用计数,并在参考计数为零时释放接口,从而消除内存泄漏。

ComPtr包含在Windows 8.x SDK and Windows 10 SDK,

如果是Windows7系统,需要下载Windows7.1 SDK

下载地址

https://www.microsoft.com/en-us/download/details.aspx?id=8442

头文件和命名空间

需要包含 <wrl/client.h>

引用 using Microsoft::WRL::ComPtr;

如何使用

这里以IFileOpenDialog为例进行演示

ComPtr提供一个Get()函数,可以检索指向与此 ComPtr 相关联的接口。

 1 HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED |
 2     COINIT_DISABLE_OLE1DDE);
 3 
 4 Microsoft::WRL::ComPtr<IFileOpenDialog> m_pFileDialog;
 5 hr = CoCreateInstance(
 6     __uuidof(FileOpenDialog),
 7     NULL,
 8     CLSCTX_INPROC_SERVER,
 9     IID_PPV_ARGS(&m_pFileDialog)
10 );
11 auto rt = m_pFileDialog.Get();
12 rt->Show(NULL);

使用智能指针后,不需要再调用Release()进行释放,关于详细的引用计数,可以访问文末参考资料里的链接进行了解。

获取新接口(QueryInterface)

可以使用ComPtrAsCopyTo函数来获取新接口,这里以WIC组件为例进行演示

 1 #include <iostream>
 2 #include<Windows.h>
 3 #include<ShlObj_core.h>
 4 #include<wrl/client.h>
 5 #include<atlbase.h>
 6 #include<wincodec.h>
 7 
 8 int main()
 9 {
10 
11     HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED |
12         COINIT_DISABLE_OLE1DDE);
13 
14     Microsoft::WRL::ComPtr<IWICImagingFactory> m_pIWICFactory;
15 
16     hr = CoCreateInstance(
17         CLSID_WICImagingFactory,
18         NULL,
19         CLSCTX_INPROC_SERVER,
20         IID_PPV_ARGS(&m_pIWICFactory)
21     );
22 
23     if (FAILED(hr))
24         return 0;
25 
26     Microsoft::WRL::ComPtr<IWICBitmapDecoder> pDecoder;
27 
28     hr = m_pIWICFactory->CreateDecoderFromFilename(
29         L"explorer_back.png",            // Image to be decoded
30         NULL,                            // Do not prefer a particular vendor
31         GENERIC_READ,                    // Desired read access to the file
32         WICDecodeMetadataCacheOnDemand,  // Cache metadata when needed
33         &pDecoder                        // Pointer to the decoder
34     );
35 
36     Microsoft::WRL::ComPtr<IWICBitmapFrameDecode> pFrame;
37 
38     // Retrieve the first frame of the image from the decoder
39     if (SUCCEEDED(hr))
40     {
41         hr = pDecoder->GetFrame(0, &pFrame);
42     }
43 
44     Microsoft::WRL::ComPtr<IWICBitmapSource> m_pOriginalBitmapSource;
45     // Retrieve IWICBitmapSource from the frame
46     if (SUCCEEDED(hr))
47     {
48         //ComPtr provides a much simpler syntax for doing QueryInterface calls on COM Objects
49         //You can also use CopyTo to perform similar operations to As.     
50         hr = pFrame.As(&m_pOriginalBitmapSource);
51 
52         //QueryInterface
53         /*
54         *  hr = pFrame->QueryInterface(
55         *        IID_IWICBitmapSource, 
56         *        reinterpret_cast<void **>(&m_pOriginalBitmapSource));
57         */
58 
59         //...
60     }
61     return 0;
62 }

清空ComPtr

可以使用ComPtrReset()函数

或者直接设置为nullptr

如下所示

1  //Clearing
2  m_pFileDialog.Reset(); //or m_pFileDialog = nullptr;

判断是否为空

与许多智能指针一样,ComPtr有一个运算符bool重载,可以很方便检查ComPtr当前是否设置为null,如下所示:

 1 ComPtr<ID3D11Debug> d3dDebug;
 2 
 3 ...
 4 
 5 if ( !d3dDebug )
 6     {
 7         d3dDebug is null
 8     }
 9 ...
10 assert( d3dDebug ); // trigger error if d3dDebug is null

其它注意事项

1、在C++/WinRT 项目中,应该使用winrt::com_ptr 而不是 Microsoft::WRL:ComPtr,可以查看Microsoft Docs.

2、开启了/clr支持的托管C++是不能使用WRL的,这时候可以使用ATL里面的CComPtr,原理和ComPtr一样,使用方法有一点小区别,可以查看Microsoft Docs.

3、本文只介绍了ComPtr的基础使用,如果想了解得更深入一点,可以访问参考链接里的文章。

示例代码

参考链接:

ComPtr wiki

ComPtr · microsoft/DirectXTK Wiki · GitHub

ComPtr Class | Microsoft Learn

why-dont-modern-smart-pointers-implicitly-convert-to

Reader Q&A: Why don’t modern smart pointers implicitly convert to *? – Sutter’s Mill

ComPtrExamples

https://cpp.hotexamples.com/examples/microsoft.wrl/ComPtr/-/cpp-comptr-class-examples.html

ComSmartPointer

COM Coding Practices - Win32 apps | Microsoft Learn

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

△曉風殘月〆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值