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)
可以使用ComPtr的As或CopyTo函数来获取新接口,这里以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
可以使用ComPtr的Reset()函数
或者直接设置为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

1768

被折叠的 条评论
为什么被折叠?



