YSTest  PreAlpha_b500_20140530
The YSLib Test Project
 全部  命名空间 文件 函数 变量 类型定义 枚举 枚举值 友元 宏定义  
include/YCLib/COM.h
浏览该文件的文档.
1 /*
2  © 2013-2014 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_MinGW32_YCLib_MinGW32
34 #include <objbase.h>
35 
36 namespace platform_ex
37 {
38 
40 
41 class YF_API COM
43 {
44 protected:
46  ::HRESULT hResult;
47 
48 public:
49  COM()
50  : hResult(::CoInitialize(nullptr))
51  {}
52  ~COM()
53  {
54  if(hResult == S_OK)
55  ::CoUninitialize();
56  }
57 
59  DefGetter(ynothrow, ::HRESULT, HResult, hResult)
60 };
61 
62 
64 class YF_API COMException : public std::runtime_error
65 {
66 protected:
67  ::HRESULT hResult;
68 
69 public:
70  COMException(::HRESULT h)
71  : runtime_error("COMException"), hResult(h)
72  {
73  yconstraint(FAILED(h) || h == S_FALSE);
74  }
75 
76  DefGetter(ynothrow, ::HRESULT, HResult, hResult)
77 };
78 
79 
84 inline ::HRESULT
86 {
87  if(FAILED(h))
88  throw COMException(h);
89  return h;
90 }
91 
95 inline void
97 {
98  if(!p)
99  throw COMException(S_FALSE);
100 }
101 
102 
103 /*
104 \brief COM 指针。
105 \warning 非虚析构。
106 */
107 template<class _iCOM>
108 class COMPtr
109 {
110  template<class _iOther>
111  friend class COMPtr;
112 
113 public:
114  using InterfaceType = _iCOM;
115 
116 protected:
118 
119 public:
121  : pInterface()
122  {}
123  COMPtr(std::nullptr_t) ynothrow
124  : pInterface()
125  {}
126  template<class _iOther>
127  COMPtr(_iOther* ptr) ynothrow
128  : pInterface(ptr)
129  {}
131  template<class _iOther>
132  COMPtr(_iOther& intf, ystdex::enable_if_t<!std::is_convertible<_iOther&,
133  COMPtr&>::value, int> = 0) ynothrow
134  : pInterface(&intf)
135  {
136  pInterface->AddRef();
137  }
138  COMPtr(const COMPtr& ptr) ynothrow
139  : pInterface(ptr.pInterface)
140  {
141  InternalAddRef();
142  }
144  template<class _iOther>
146  std::is_convertible<_iOther*, _iCOM*>::value, int> = 0) ynothrow
147  : pInterface(ptr.pInterface)
148  {
149  InternalAddRef();
150  }
152  : pInterface()
153  {
154  ptr.swap(*this);
155  }
157  template<class _iOther>
159  std::is_convertible<_iOther*, _iCOM*>::value, int> = 0) ynothrow
160  : pInterface(ptr.pInterface)
161  {
162  ptr.pInterface = nullptr;
163  }
166  {
167  InternalRelease();
168  }
169 
170  COMPtr&
171  operator=(std::nullptr_t) ynothrow
172  {
173  InternalRelease();
174  return *this;
175  }
176  COMPtr&
177  operator=(_iCOM* p) ynothrow
178  {
179  if(pInterface != p)
180  COMPtr(p).swap(*this);
181  return *this;
182  }
183  COMPtr&
185  {
186  COMPtr(ptr).swap(*this);
187  return *this;
188  }
189  COMPtr&
191  {
192  ptr.swap(*this);
193  return *this;
194  }
195 
197  _iCOM&
199  {
201  return *pInterface;
202  }
203 
204  _iCOM*
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 
220  COMPtr<IUnknown>
221  As(REFIID riid) const ythrow(COMException)
222  {
223  yconstraint(pInterface);
224 
225  COMPtr<IUnknown> res;
226 
227  CheckHResult(pInterface->QueryInterface(riid,
228  reinterpret_cast<void**>(&res.ReleaseAndGetRef())));
229  return res;
230  }
231  template<class _iOther>
234  {
236 
237  COMPtr<_iOther> res;
238 
239  CheckHResult(pInterface->QueryInterface(__uuidof(_iOther),
240  reinterpret_cast<void**>(&res.ReleaseAndGetRef())));
241  return res;
242  }
243 
244  ::HRESULT
245  Cast(REFIID riid, COMPtr<IUnknown>& ptr) const ynothrow
246  {
248  return pInterface->QueryInterface(riid,
249  reinterpret_cast<void**>(&ptr.ReleaseAndGetRef()));
250  }
251  template<class _iOther>
252  ::HRESULT
254  {
256  return pInterface->QueryInterface(__uuidof(_iOther),
257  reinterpret_cast<void**>(&ptr.ReleaseAndGetRef()));
258  }
259 
261  Copy() const ynothrow
262  {
263  InternalAddRef();
264  return pInterface;
265  }
266  void*
267  Copy(REFIID riid) const ythrow(COMException)
268  {
270 
271  void* p;
272 
273  CheckHResult(pInterface->QueryInterface(riid, &p));
274  return p;
275  }
276 
277  ::HRESULT
278  CopyTo(REFIID riid, void** ptr) const ynothrow
279  {
281  return pInterface->QueryInterface(riid, ptr);
282  }
283  template<typename _type>
284  ::HRESULT
285  CopyTo(_type*& p) const ynothrow
286  {
287  return pInterface->QueryInterface(__uuidof(_type),
288  reinterpret_cast<void**>(&p));
289  }
290 
291 protected:
292  void
294  {
295  if(pInterface)
296  pInterface->AddRef();
297  }
298 
299  void
301  {
302  if(const auto tmp = pInterface)
303  {
304  pInterface = nullptr;
305  tmp->Release();
306  }
307  }
308 
309 public:
310  _iCOM*&
312  {
313  InternalRelease();
314  return pInterface;
315  }
316 
317  void
319  {
320  std::swap(pInterface, ptr.pInterface);
321  }
322 };
323 
325 
326 template<class _iCOM1, class _iCOM2>
327 inline bool
329 {
330  static_assert(std::is_base_of<_iCOM1, _iCOM2>::value
331  || std::is_base_of<_iCOM1, _iCOM2>::value,
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
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(std::is_base_of<_iCOM1, _iCOM2>::value
374  || std::is_base_of<_iCOM1, _iCOM2>::value,
375  "'_iCOM1' and '_iCOM2' pointers must be comparable");
376 
377  return x.Get() < y.Get();
378 }
379 
380 template<class _iCOM>
381 void
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*
397 {
398  auto p(ptr.Get());
399 
400  ptr.GetRef() = nullptr;
401  return p;
402 }
403 
404 template<class _iCOM>
405 unsigned long
407 {
408  auto n(0UL);
409 
410  if(const auto tmp = ptr.Get())
411  {
412  ptr.GetRef() = nullptr;
413  n = tmp->Release();
414  }
415  return n;
416 }
417 
418 template<class _iCOM>
419 inline DefSwap(ynothrow, COMPtr<_iCOM>)
421 
422 
423 } // namespace platform_ex;
424 
425 #endif
426 
void InternalRelease() ynothrow
#define ynothrowv
YSLib 无异常抛出保证验证:有条件地使用无异常抛出规范。
Definition: ydef.h:494
#define yunused(...)
标记未使用的表达式。
Definition: ydef.h:697
COMPtr< _iOther > As() const ythrow(COMException)
_iCOM * Detach(COMPtr< _iCOM > &ptr) ynothrow
COMPtr(std::nullptr_t) ynothrow
COMPtr & operator=(std::nullptr_t) ynothrow
COMPtr(const COMPtr< _iOther > &ptr, ystdex::enable_if_t< std::is_convertible< _iOther *, _iCOM * >::value, int >=0) ynothrow
#define YF_API
Definition: Platform.h:64
_iCOM *& ReleaseAndGetRef() ynothrow
const class ystdex::nullptr_t nullptr
::HRESULT CopyTo(REFIID riid, void **ptr) const ynothrow
void EnsureNonNull(void *p) ythrow(COMException)
检查指针值,若为空则抛出 COMException 。
#define DefGetter(_q, _t, _n,...)
Definition: YBaseMacro.h:180
void swap(any &x, any &y)
交换对象。
Definition: any.h:729
COMPtr & operator=(_iCOM *p) ynothrow
#define yassume
假定:环境语义。
Definition: cassert.h:58
#define ynothrow
YSLib 无异常抛出保证:若支持 noexcept 关键字, 指定特定的 noexcept 异常规范。
Definition: ydef.h:514
COMPtr(_iOther *ptr) ynothrow
#define ythrow(...)
YSLib 动态异常规范:根据是否使用异常规范宏指定或忽略动态异常规范。
Definition: ydef.h:476
#define yconstraint
约束:接口语义。
Definition: cassert.h:47
_iCOM EnsureNonNull(pInterface)
bool operator!=(const COMPtr< _iCOM1 > &x, const COMPtr< _iCOM2 > &y) ynothrow
_iCOM & operator*() const ynothrowv
void Attach(COMPtr< _iCOM > &ptr, typename COMPtr< _iCOM >::InterfaceType *p) ynothrow
unsigned long Reset(COMPtr< _iCOM > &ptr) ynothrow
_iCOM * operator->() const ynothrow
::HRESULT Cast(REFIID riid, COMPtr< IUnknown > &ptr) const ynothrow
::HRESULT CopyTo(_type *&p) const ynothrow
void InternalAddRef() const ynothrow
COMPtr(COMPtr &&ptr) ynothrow
bool operator==(const COMPtr< _iCOM1 > &x, const COMPtr< _iCOM2 > &y) ynothrow
COM 异常基类。
InterfaceType * Copy() const ynothrow
COMPtr & operator=(const COMPtr &ptr) ynothrow
::HRESULT Cast(COMPtr< _iOther > &ptr) const ynothrow
DefGetter(const ynothrow, _iCOM *,, pInterface) DefGetter(const
COMPtr(_iOther &intf, ystdex::enable_if_t<!std::is_convertible< _iOther &, COMPtr & >::value, int >=0) ynothrow
void * Copy(REFIID riid) const ythrow(COMException)
InterfaceType * pInterface
COMPtr & operator=(COMPtr &&ptr) ynothrow
COMPtr(const COMPtr &ptr) ynothrow
COMPtr(COMPtr< _iOther > &&ptr, ystdex::enable_if_t< std::is_convertible< _iOther *, _iCOM * >::value, int >=0) ynothrow
typename enable_if< _bCond, _type >::type enable_if_t
Definition: type_op.hpp:274
inline::HRESULT CheckHResult(::HRESULT h) ythrow(COMException)
检查 ::HRESULT 值,若表示失败则抛出 COMException 。
void swap(COMPtr &ptr) ynothrow