From 09278fdb79b8c8490fe83f9f1331f318ccbec8da Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 15 Apr 2012 23:18:08 +0000 Subject: [PATCH] Added wxCOMPtr<> helper class. This allows to avoid error-prone manual AddRef() and Release() calls when writing COM code in wxMSW. See #11401. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@71200 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/msw/private/comptr.h | 130 ++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 include/wx/msw/private/comptr.h diff --git a/include/wx/msw/private/comptr.h b/include/wx/msw/private/comptr.h new file mode 100644 index 0000000000..26c21573d1 --- /dev/null +++ b/include/wx/msw/private/comptr.h @@ -0,0 +1,130 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: wx/msw/private/comptr.h +// Purpose: Smart pointer for COM interfaces. +// Author: PB +// Created: 2012-04-16 +// RCS-ID: $Id: $ +// Copyright: (c) 2012 wxWidgets team +// Licence: wxWindows licence +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _WX_MSW_PRIVATE_COMPTR_H_ +#define _WX_MSW_PRIVATE_COMPTR_H_ + +// ---------------------------------------------------------------------------- +// wxCOMPtr: Minimalistic a smart pointer for use with COM interfaces. +// ---------------------------------------------------------------------------- + +template +class wxCOMPtr +{ +public: + typedef T element_type; + + wxCOMPtr() + : m_ptr(NULL) + { + } + + wxEXPLICIT wxCOMPtr(T* ptr) + : m_ptr(ptr) + { + if ( m_ptr ) + m_ptr->AddRef(); + } + + wxCOMPtr(const wxCOMPtr& ptr) + : m_ptr(ptr.get()) + { + if ( m_ptr ) + m_ptr->AddRef(); + } + + ~wxCOMPtr() + { + if ( m_ptr ) + m_ptr->Release(); + } + + void reset(T* ptr = NULL) + { + if ( m_ptr != ptr) + { + if ( ptr ) + ptr->AddRef(); + if ( m_ptr ) + m_ptr->Release(); + m_ptr = ptr; + } + } + + wxCOMPtr& operator=(const wxCOMPtr& ptr) + { + reset(ptr.get()); + return *this; + } + + wxCOMPtr& operator=(T* ptr) + { + reset(ptr); + return *this; + } + + operator T*() const + { + return m_ptr; + } + + T& operator*() const + { + return *m_ptr; + } + + T* operator->() const + { + return m_ptr; + } + + // It would be better to forbid direct access completely but we do need + // for QueryInterface() and similar functions, so provide it but it can + // only be used to initialize the pointer, not to modify an existing one. + T** operator&() + { + wxASSERT_MSG(!m_ptr, + wxS("Can't get direct access to initialized pointer")); + + return &m_ptr; + } + + T* get() const + { + return m_ptr; + } + + bool operator<(T* ptr) const + { + return get() < ptr; + } + +private: + T* m_ptr; +}; + +// Define a helper for the macro below: we just need a function taking a +// pointer and not returning anything to avoid warnings about unused return +// value of the cast in the macro itself. +namespace wxPrivate { void PPV_ARGS_CHECK(void*) { } } + +// Takes the interface name and a pointer to a pointer of the interface type +// and expands into the IID of this interface and the same pointer but after a +// type-safety check. +// +// This is similar to the standard IID_PPV_ARGS macro but takes the pointer +// type instead of relying on the non-standard Microsoft __uuidof(). +#define wxIID_PPV_ARGS(IType, pType) \ + IID_##IType, \ + (wxPrivate::PPV_ARGS_CHECK(static_cast(*pType)), \ + reinterpret_cast(pType)) + +#endif // _WX_MSW_PRIVATE_COMPTR_H_ + -- 2.45.2