YSTest: COM.h 源文件

YSTest PreAlpha_b800_20170810 The YSLib Test Project

- 首页
- 相关页面
- 模块
- 命名空间
- 类
- 文件

- 文件列表
- 文件成员

COM.h
浏览该文件的文档.
1 /*
2 © 2013-2016 FrankHB.
3
4 This file is part of the YSLib project, and may only be used,
5 modified, and distributed under the terms of the YSLib project
6 license, LICENSE.TXT. By continuing to use, modify, or distribute
7 this file you indicate that you have read the license and
8 understand and accept it fully.
9 */
10
29 #ifndef YCL_MinGW32_INC_COMPtr_h_
30 #define YCL_MinGW32_INC_COMPtr_h_ 1
31
32 #include "YCLib/YModules.h"
33 #include YFM_Win32_YCLib_MinGW32 // for platform_ex, std::runtime_error,
34 // ystdex::enable_if_t, std::is_convertible, std::nullptr_t,
35 // ystdex::replace_cast;
36 #include <objbase.h> // for ::HRESULT, ::CoInitialize, S_OK, ::CoUnitialize,
37 // FAILED, S_FALSE, ::IID;
38
39 namespace platform_ex
40 {
41
43
44 class YF_API COM
46 {
47 protected:
49 ::HRESULT hResult;
50
51 public:
52 COM()
53 : hResult(::CoInitialize(nullptr))
54 {}
55 ~COM()
56 {
57 if(hResult == S_OK)
58 ::CoUninitialize();
59 }
60
62 DefGetter(ynothrow, ::HRESULT, HResult, hResult)
63 };
64
65
67 class YF_API COMException : public std::runtime_error
68 {
69 protected:
70 ::HRESULT hResult;
71
72 public:
73 COMException(::HRESULT h)
74 : runtime_error("COMException"), hResult(h)
75 {
76 YAssert(FAILED(h) || h == S_FALSE, "Invalid argument found.");
77 }
78
79 DefGetter(ynothrow, ::HRESULT, HResult, hResult)
80 };
81
82
88 inline ::HRESULT
89 CheckHResult(::HRESULT h)
90 {
91 if(FAILED(h))
92 throw COMException(h);
93 return h;
94 }
95
100 inline PDefH(void, EnsureNonNull, void* p)
101 ImplExpr(p ? void() : throw COMException(S_FALSE))
102
103
104
108 template<class _iCOM>
109 class COMPtr
110 {
111 template<class _iOther>
112 friend class COMPtr;
113
114 public:
115 using InterfaceType = _iCOM;
116
117 protected:
118 InterfaceType* pInterface;
119
120 public:
121 COMPtr() ynothrow
122 : pInterface()
123 {}
124 COMPtr(std::nullptr_t) ynothrow
125 : pInterface()
126 {}
127 template<class _iOther>
128 COMPtr(_iOther* ptr) ynothrow
129 : pInterface(ptr)
130 {}
132 template<class _iOther>
133 COMPtr(_iOther& intf, ystdex::enable_if_t<!std::is_convertible<_iOther&,
134 COMPtr&>::value, int> = 0) ynothrow
135 : pInterface(&intf)
136 {
137 pInterface->AddRef();
138 }
139 COMPtr(const COMPtr& ptr) ynothrow
140 : pInterface(ptr.pInterface)
141 {
142 InternalAddRef();
143 }
145 template<class _iOther>
146 COMPtr(const COMPtr<_iOther>& ptr, ystdex::enable_if_t<
147 std::is_convertible<_iOther*, _iCOM*>::value, int> = 0) ynothrow
148 : pInterface(ptr.pInterface)
149 {
150 InternalAddRef();
151 }
152 COMPtr(COMPtr&& ptr) ynothrow
153 : pInterface()
154 {
155 ptr.swap(*this);
156 }
158 template<class _iOther>
159 COMPtr(COMPtr<_iOther>&& ptr, ystdex::enable_if_t<
160 std::is_convertible<_iOther*, _iCOM*>::value, int> = 0) ynothrow
161 : pInterface(ptr.pInterface)
162 {
163 ptr.pInterface = nullptr;
164 }
166 ~COMPtr()
167 {
168 InternalRelease();
169 }
170
171 COMPtr&
172 operator=(std::nullptr_t) ynothrow
173 {
174 InternalRelease();
175 return *this;
176 }
177 COMPtr&
178 operator=(_iCOM* p) ynothrow
179 {
180 if(pInterface != p)
181 COMPtr(p).swap(*this);
182 return *this;
183 }
184 COMPtr&
185 operator=(const COMPtr& ptr) ynothrow
186 {
187 COMPtr(ptr).swap(*this);
188 return *this;
189 }
190 COMPtr&
191 operator=(COMPtr&& ptr) ynothrow
192 {
193 ptr.swap(*this);
194 return *this;
195 }
196
198 _iCOM&
199 operator*() const ynothrowv
200 {
201 return Deref(pInterface);
202 }
203
204 _iCOM*
205 operator->() const ynothrow
206 {
207 return pInterface;
208 }
209
210 explicit
211 operator bool() const ynothrow
212 {
213 return Get() != nullptr;
214 }
215
216 DefGetter(const ynothrow, _iCOM*, , pInterface)
217 DefGetter(const, _iCOM&, Object, EnsureNonNull(pInterface), *pInterface)
218 DefGetter(ynothrow, _iCOM*&, Ref, pInterface)
219
225 COMPtr<IUnknown>
227 As(const ::IID& riid) const
228 {
229 COMPtr<IUnknown> res;
230
231 CheckHResult(Deref(pInterface).QueryInterface(riid,
232 ystdex::replace_cast<void**>(&res.ReleaseAndGetRef())));
233 return res;
234 }
235 template<class _iOther>
236 COMPtr<_iOther>
237 As() const
238 {
239 COMPtr<_iOther> res;
240
241 CheckHResult(Deref(pInterface).QueryInterface(__uuidof(_iOther),
242 ystdex::replace_cast<void**>(&res.ReleaseAndGetRef())));
243 return res;
244 }
246
248 ::HRESULT
249 Cast(const ::IID& riid, COMPtr<IUnknown>& ptr) const ynothrow
250 {
251 return Deref(pInterface).QueryInterface(riid,
252 ystdex::replace_cast<void**>(&ptr.ReleaseAndGetRef()));
253 }
254 template<class _iOther>
255 ::HRESULT
256 Cast(COMPtr<_iOther>& ptr) const ynothrow
257 {
258 YAssertNonnull(pInterface);
259 return pInterface->QueryInterface(__uuidof(_iOther),
260 ystdex::replace_cast<void**>(&ptr.ReleaseAndGetRef()));
261 }
262
263 InterfaceType*
264 Copy() const ynothrow
265 {
266 InternalAddRef();
267 return pInterface;
268 }
270 void*
271 Copy(const ::IID& riid) const
272 {
273 void* p;
274
275 CheckHResult(Deref(pInterface).QueryInterface(riid, &p));
276 return p;
277 }
278
280 ::HRESULT
281 CopyTo(const ::IID& riid, void** ptr) const ynothrow
282 {
283 return Deref(pInterface).QueryInterface(riid, ptr);
284 }
285 template<typename _type>
286 ::HRESULT
287 CopyTo(_type*& p) const ynothrow
288 {
289 return pInterface->QueryInterface(__uuidof(_type),
290 ystdex::replace_cast<void**>(&p));
291 }
292
293 protected:
294 void
295 InternalAddRef() const ynothrow
296 {
297 if(pInterface)
298 pInterface->AddRef();
299 }
300
301 void
302 InternalRelease() ynothrow
303 {
304 if(const auto tmp = pInterface)
305 {
306 pInterface = {};
307 tmp->Release();
308 }
309 }
310
311 public:
312 _iCOM*&
313 ReleaseAndGetRef() ynothrow
314 {
315 InternalRelease();
316 return pInterface;
317 }
318
320 PDefH(void, swap, COMPtr& x, COMPtr& y) ynothrow
321 ImplExpr(std::swap(x.pInterface, y.pInterface))
322 };
323
325
326 template<class _iCOM1, class _iCOM2>
327 inline bool
328 operator==(const COMPtr<_iCOM1>& x, const COMPtr<_iCOM2>& y) ynothrow
329 {
330 static_assert(ystdex::or_<std::is_base_of<_iCOM1, _iCOM2>,
331 std::is_base_of<_iCOM1, _iCOM2>>(),
332 "'_iCOM1' and '_iCOM2' pointers must be comparable");
333
334 return x.Get() == y.Get();
335 }
336 template<class _iCOM>
337 inline bool
338 operator==(const COMPtr<_iCOM>& x, std::nullptr_t) ynothrow
339 {
340 return !x.Get();
341 }
342 template<class _iCOM>
343 inline bool
344 operator==(std::nullptr_t, const COMPtr<_iCOM>& x) ynothrow
345 {
346 return !x.Get();
347 }
348
349 template<class _iCOM1, class _iCOM2>
350 inline bool
351 operator!=(const COMPtr<_iCOM1>& x, const COMPtr<_iCOM2>& y) ynothrow
352 {
353 return !(x == y);
354 }
355 template<class _iCOM>
356 inline bool
357 operator!=(const COMPtr<_iCOM>& x, std::nullptr_t) ynothrow
358 {
359 return x.Get();
360 }
361
362 template<class _iCOM>
363 inline bool
364 operator!=(std::nullptr_t, const COMPtr<_iCOM>& x) ynothrow
365 {
366 return x.Get();
367 }
368
369 template<class _iCOM1, class _iCOM2>
370 inline bool
371 operator<(const COMPtr<_iCOM1>& x, const COMPtr<_iCOM2>& y) ynothrow
372 {
373 static_assert(ystdex::or_<std::is_base_of<_iCOM1, _iCOM2>,
374 std::is_base_of<_iCOM1, _iCOM2>>(),
375 "'_iCOM1' and '_iCOM2' pointers must be comparable");
376
377 return x.Get() < y.Get();
378 }
379
380 template<class _iCOM>
381 void
382 Attach(COMPtr<_iCOM>& ptr, typename COMPtr<_iCOM>::InterfaceType* p) ynothrow
383 {
384 if(const auto p_interface = ptr.Get())
385 {
386 const auto ref(p_interface->Release());
387
388 yunused(ref);
389 yassume(ref != 0 || p_interface != p);
390 }
391 ptr.GetRef() = ptr;
392 }
393
394 template<class _iCOM>
395 _iCOM*
396 Detach(COMPtr<_iCOM>& ptr) ynothrow
397 {
398 auto p(ptr.Get());
399
400 ptr.GetRef() = nullptr;
401 return p;
402 }
403
404 template<class _iCOM>
405 unsigned long
406 Reset(COMPtr<_iCOM>& ptr) ynothrow
407 {
408 auto n(0UL);
409
410 if(const auto tmp = ptr.Get())
411 {
412 ptr.GetRef() = {};
413 n = tmp->Release();
414 }
415 return n;
416 }
418
419
420 } // namespace platform_ex;
421
422 #endif
423
platform_ex::COMException
COM 异常基类。
Definition: COM.h:67
platform_ex::operator!=
bool operator!=(const COMPtr< _iCOM1 > &x, const COMPtr< _iCOM2 > &y) ynothrow
Definition: COM.h:351
platform_ex::Detach
_iCOM * Detach(COMPtr< _iCOM > &ptr) ynothrow
Definition: COM.h:396
platform_ex::COM::hResult
::HRESULT hResult
Definition: COM.h:49
platform::Deref
yconstfn auto Deref(_type &&p) -> decltype(*p)
断言并解引用非空指针。
Definition: Debug.h:451
YSLib::UI::y
SPos SPos y
Definition: YWidget.cpp:44
NPL::x
const TermNode &term ynothrow const TermNode &term ynothrow const TermNode &term ynothrow TermNode &term const TermNode &term ValueNode &node const ValueNode &node const _type & x
Definition: SContext.h:94
platform_ex::COMException::COMException
COMException(::HRESULT h)
Definition: COM.h:73
ystdex::or_
Definition: type_traits.hpp:438
platform::bool
std::FILE *fp bool
Definition: FileIO.h:1280
YAssertNonnull
#define YAssertNonnull(_expr)
Definition: cassert.h:120
ystdex::cpp2014::enable_if_t
typename enable_if< _bCond, _type >::type enable_if_t
Definition: type_traits.hpp:343
ystdex::nullptr
const class ystdex::nullptr_t nullptr
YAssert
#define YAssert(_expr, _msg)
Definition: cassert.h:111
platform_ex::operator==
PDefH(void, EnsureNonNull, void *p) ImplExpr(p?void() boo operator==)(const COMPtr< _iCOM1 > &x, const COMPtr< _iCOM2 > &y) ynothrow
检查指针值，若为空则抛出 COMException 。
Definition: COM.h:328
ynothrow
#define ynothrow
YSLib 无异常抛出保证：若支持 noexcept 关键字， 指定特定的 noexcept 异常规范。
Definition: ydef.h:766
YF_API
#define YF_API
Definition: Platform.h:56
platform_ex::COMException::hResult
::HRESULT hResult
Definition: COM.h:70
YModules.h
YSLib::Drawing::CopyTo
bool CopyTo(BitmapPtr dst, const ConstGraphics &g, const Size &ds, const Point &dp, const Point &sp, const Size &sc, Rotation rot)
Definition: YGDI.cpp:203
yunused
#define yunused(...)
标记未使用的表达式。
Definition: ydef.h:968
ynothrowv
#define ynothrowv
YSLib 无异常抛出保证验证：有条件地使用无异常抛出规范。
Definition: ydef.h:786
platform_ex::Reset
unsigned long Reset(COMPtr< _iCOM > &ptr) ynothrow
Definition: COM.h:406
ystdex::swap
void swap(container_adaptor< _tSeqCon > &x, container_adaptor< _tSeqCon > &y)
Definition: container.hpp:179
DefGetter
#define DefGetter(_q, _t, _n,...)
Definition: YBaseMacro.h:241
platform_ex::COM::~COM
~COM()
Definition: COM.h:55
platform_ex
平台扩展命名空间。
Definition: Android.h:45
platform_ex::Attach
void Attach(COMPtr< _iCOM > &ptr, typename COMPtr< _iCOM >::InterfaceType *p) ynothrow
Definition: COM.h:382
yassume
#define yassume(_expr)
假定：环境语义。
Definition: cassert.h:105
platform_ex::CheckHResult
inline::HRESULT CheckHResult(::HRESULT h)
检查 ::HRESULT 值，若表示失败则抛出 COMException 。
Definition: COM.h:89
ystdex::ref
lref< _type > ref(_type &t)
构造引用包装。
Definition: ref.hpp:132
platform_ex::COM::COM
COM()
Definition: COM.h:52
CHRLib::p
const auto p(d)