YSTest  PreAlpha_b500_20140530
The YSLib Test Project
 全部  命名空间 文件 函数 变量 类型定义 枚举 枚举值 友元 宏定义  
E/include/YCLib/COM.h
浏览该文件的文档.
1 /*
2  Copyright by FrankHB 2013.
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 "MinGW32.h"
33 #include <objbase.h>
34 
35 namespace platform_ex
36 {
37 
39 
40 class YF_API COM
42 {
43 protected:
45  ::HRESULT hResult;
46 
47 public:
48  COM()
49  : hResult(::CoInitialize(nullptr))
50  {}
51  ~COM()
52  {
53  if(hResult == S_OK)
54  ::CoUninitialize();
55  }
56 
58  DefGetter(ynothrow, ::HRESULT, HResult, hResult)
59 };
60 
61 
63 class YF_API COMException : public std::runtime_error
64 {
65 protected:
66  ::HRESULT hResult;
67 
68 public:
69  COMException(::HRESULT h)
70  : runtime_error("COMException"), hResult(h)
71  {
72  yconstraint(FAILED(h) || h == S_FALSE);
73  }
74 
75  DefGetter(ynothrow, ::HRESULT, HResult, hResult)
76 };
77 
78 
83 inline ::HRESULT
84 CheckHResult(::HRESULT h) ythrow(COMException)
85 {
86  if(FAILED(h))
87  throw COMException(h);
88  return h;
89 }
90 
94 inline void
95 EnsureNonNull(void* p) ythrow(COMException)
96 {
97  if(!p)
98  throw COMException(S_FALSE);
99 }
100 
101 
102 /*
103 \brief COM 指针。
104 \warning 非虚析构。
105 */
106 template<class _iCOM>
107 class COMPtr
108 {
109  template<class _iOther>
110  friend class COMPtr;
111 
112 public:
113  using InterfaceType = _iCOM;
114 
115 protected:
117 
118 public:
120  : pInterface()
121  {}
122  COMPtr(std::nullptr_t) ynothrow
123  : pInterface()
124  {}
125  template<class _iOther>
126  COMPtr(_iOther* ptr) ynothrow
127  : pInterface(ptr)
128  {}
130  template<class _iOther>
131  COMPtr(_iOther& intf, ystdex::enable_if_t<!std::is_convertible<_iOther&,
132  COMPtr&>::value, int> = 0) ynothrow
133  : pInterface(&intf)
134  {
135  pInterface->AddRef();
136  }
137  COMPtr(const COMPtr& ptr) ynothrow
138  : pInterface(ptr.pInterface)
139  {
140  InternalAddRef();
141  }
143  template<class _iOther>
145  std::is_convertible<_iOther*, _iCOM*>::value, int> = 0) ynothrow
146  : pInterface(ptr.pInterface)
147  {
148  InternalAddRef();
149  }
151  : pInterface()
152  {
153  ptr.swap(*this);
154  }
156  template<class _iOther>
158  std::is_convertible<_iOther*, _iCOM*>::value, int> = 0) ynothrow
159  : pInterface(ptr.pInterface)
160  {
161  ptr.pInterface = nullptr;
162  }
164  {
165  InternalRelease();
166  }
167 
168  COMPtr&
169  operator=(std::nullptr_t) ynothrow
170  {
171  InternalRelease();
172  return *this;
173  }
174  COMPtr&
175  operator=(_iCOM* p) ynothrow
176  {
177  if(pInterface != p)
178  COMPtr(p).swap(*this);
179  return *this;
180  }
181  COMPtr&
183  {
184  COMPtr(ptr).swap(*this);
185  return *this;
186  }
187  COMPtr&
189  {
190  ptr.swap(*this);
191  return *this;
192  }
193 
194  _iCOM&
196  {
198 
199  return *pInterface;
200  }
201 
202  _iCOM*
204  {
205  return pInterface;
206  }
207 
208  explicit
209  operator bool() const ynothrow
210  {
211  return Get() != nullptr;
212  }
213 
214  DefGetter(const ynothrow, _iCOM*, , pInterface)
215  DefGetter(const, _iCOM&, Object, EnsureNonNull(pInterface), *pInterface)
216  DefGetter(ynothrow, _iCOM*&, Ref, pInterface)
217 
218  COMPtr<IUnknown>
219  As(REFIID riid) const ythrow(COMException)
220  {
221  yconstraint(pInterface);
222 
223  COMPtr<IUnknown> res;
224 
225  CheckHResult(pInterface->QueryInterface(riid,
226  reinterpret_cast<void**>(&res.ReleaseAndGetRef())));
227  return std::move(res);
228  }
229  template<class _iOther>
232  {
234 
235  COMPtr<_iOther> res;
236 
237  CheckHResult(pInterface->QueryInterface(__uuidof(_iOther),
238  reinterpret_cast<void**>(&res.ReleaseAndGetRef())));
239  return std::move(res);
240  }
241 
242  ::HRESULT
243  Cast(REFIID riid, COMPtr<IUnknown>& ptr) const ynothrow
244  {
246 
247  return pInterface->QueryInterface(riid,
248  reinterpret_cast<void**>(&ptr.ReleaseAndGetRef()));
249  }
250  template<class _iOther>
251  ::HRESULT
253  {
255 
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 
282  return pInterface->QueryInterface(riid, ptr);
283  }
284  template<typename _type>
285  ::HRESULT
286  CopyTo(_type*& p) const ynothrow
287  {
288  return pInterface->QueryInterface(__uuidof(_type),
289  reinterpret_cast<void**>(&p));
290  }
291 
292 protected:
293  void
295  {
296  if(pInterface)
297  pInterface->AddRef();
298  }
299 
300  void
302  {
303  if(const auto tmp = pInterface)
304  {
305  pInterface = nullptr;
306  tmp->Release();
307  }
308  }
309 
310 public:
311  _iCOM*&
313  {
314  InternalRelease();
315  return pInterface;
316  }
317 
318  void
320  {
321  std::swap(pInterface, ptr.pInterface);
322  }
323 };
324 
326 
327 template<class _iCOM1, class _iCOM2>
328 inline bool
329 operator==(const COMPtr<_iCOM1>& x, const COMPtr<_iCOM2>& y) ynothrow
330 {
331  static_assert(std::is_base_of<_iCOM1, _iCOM2>::value
332  || std::is_base_of<_iCOM1, _iCOM2>::value,
333  "'_iCOM1' and '_iCOM2' pointers must be comparable");
334 
335  return x.Get() == y.Get();
336 }
337 template<class _iCOM>
338 inline bool
339 operator==(const COMPtr<_iCOM>& x, std::nullptr_t) ynothrow
340 {
341  return !x.Get();
342 }
343 template<class _iCOM>
344 inline bool
345 operator==(std::nullptr_t, const COMPtr<_iCOM>& x) ynothrow
346 {
347  return !x.Get();
348 }
349 
350 template<class _iCOM1, class _iCOM2>
351 inline bool
352 operator!=(const COMPtr<_iCOM1>& x, const COMPtr<_iCOM2>& y) ynothrow
353 {
354  return !(x == y);
355 }
356 template<class _iCOM>
357 inline bool
358 operator!=(const COMPtr<_iCOM>& x, std::nullptr_t) ynothrow
359 {
360  return x.Get();
361 }
362 
363 template<class _iCOM>
364 inline bool
365 operator!=(std::nullptr_t, const COMPtr<_iCOM>& x) ynothrow
366 {
367  return x.Get();
368 }
369 
370 template<class _iCOM1, class _iCOM2>
371 inline bool
372 operator<(const COMPtr<_iCOM1>& x, const COMPtr<_iCOM2>& y) ynothrow
373 {
374  static_assert(std::is_base_of<_iCOM1, _iCOM2>::value
375  || std::is_base_of<_iCOM1, _iCOM2>::value,
376  "'_iCOM1' and '_iCOM2' pointers must be comparable");
377 
378  return x.Get() < y.Get();
379 }
380 
381 template<class _iCOM>
382 void
383 Attach(COMPtr<_iCOM>& ptr, typename COMPtr<_iCOM>::InterfaceType* p) ynothrow
384 {
385  if(const auto p_interface = ptr.Get())
386  {
387  const auto ref(p_interface->Release());
388 
389  yunused(ref);
390 
391  yassume(ref != 0 || p_interface != p);
392  }
393  ptr.GetRef() = ptr;
394 }
395 
396 template<class _iCOM>
397 _iCOM*
398 Detach(COMPtr<_iCOM>& ptr) ynothrow
399 {
400  auto p(ptr.Get());
401 
402  ptr.GetRef() = nullptr;
403  return p;
404 }
405 
406 template<class _iCOM>
407 unsigned long
408 Reset(COMPtr<_iCOM>& ptr) ynothrow
409 {
410  auto n(0UL);
411 
412  if(const auto tmp = ptr.Get())
413  {
414  ptr.GetRef() = nullptr;
415  n = tmp->Release();
416  }
417  return n;
418 }
419 
420 template<class _iCOM>
421 inline DefSwap(ynothrow, COMPtr<_iCOM>)
423 
424 
425 } // namespace platform_ex;
426 
427 #endif
428 
void InternalRelease() ynothrow
#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
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
_iCOM & operator*() 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