A Pure C++ Implementation of a COM Smart Pointer

Introduction

CComPtr wraps any interface pointer and will call AddRef() and Release() properly. That is, you don’t need to worry about the life cycle of your COM interface pointer.

Am I Re-Inventing Something Here?

  1. ATL does provide a COM smart pointer class named CComQIPtr, but it uses some ATL-specific funtions inside so that it can NOT be used outside the ATL environment.
  2. Visual C++ does provide the _com_ptr_t and _bstr_ptr_t helper classes to support smart the COM pointer feature, but it only works on the Microsoft Visual C++ Compiler, without which you cannot benefit.
  3. My CComPtr provides a compiler-independent, smart pointer solution. It is currently used in our kernal driver project and well-tested.

Illustration

Note: INTERFACE & piid are passed into the CComPtr class through template parameters.

CComPtr has four constructors to meet different requirements:

  • CComPtr(): Simply a constructor; does nothing.
  • CComPtr(INTERFACE* lPtr): Constructs a new CComPtr object with an existing interface pointer. After that, this new CComPtr object can be used as an interface pointer itself.
  • CComPtr(IUnknown* pIUnknown, IID iid): Constructs a new CComPtr object with an IUnknown pointer and an IID; these represent the interface you are interested in. Internally, a constructor will call pIUnknown->QueryInterface to fetch the interface pointer according to the IID.
  • CComPtr(const CComPtr<INTERFACE, piid>& RefComPtr): This contsructor takes another existing CComPtr object as a parameter. After that, clone the old CComPtr object.

CComPtr has one destructor; it will release the interface pointer.

~CComPtr(){ if (m_Ptr) { m_Ptr->Release(); m_Ptr = NULL; } }

CComPtr has five operators:

  • Operator INTERFACE*: Returns the interface pointer wrapped by the CComPtr class.
  • Example:

    CComPtr<IWavePciStream> m_wavePciStreamPtr;
    IWavePciStream* pWavePciStream =
       (IWavePciStream*)m_wavePciStreamPtr;
    
  • Operator *: Fetches the interface object wrapped by the CComPtr class.
  • Example:

    CComPtr<IWavePciStream> m_wavePciStreamPtr;
    IWavePciStream wavePciStream = *m_wavePciStreamPtr;
    
  • Operator &: Fetches the pointer to an interface pointer wrapped by the CComPtr class.
  • Example:

    CComPtr<IWavePciStream> m_wavePciStreamPtr;
    IWavePciStream** ppWavePciStream = &m_wavePciStreamPtr;
    
  • Operator ->: Makes a CComPtr object act as a TRUE interface pointer.
  • Example:

    CComPtr<IWavePciStream> m_wavePciStreamPtr;
    m_wavePciStreamPtr->AnyPciStreamMethods();
    
  • Operator =: Transfers exsiting interface pointer information to a new CComPtr object. This operator has three different parameters:
    1. There is an INTERFACE* in the parameter.
    2. There is another CComPtr object in the parameter.
    3. There is an interface pointer to IUnknown in the parameter. It will be used to query other interface pointer defined by piid.

CComPtr has another three methods:

  • Attach: Attaches an existing interface pointer to a CComPtr object
  • Detach: Detaches an interface pointer from a CComPtr object
  • Release: Releases the wrapped interface pointer explicitly

CComPtr is implemented in pure C++. That is, it does not depend on any specific C/C++ compiler and can be compiled under any ANSI C/C++-compliant compiler. I have tested in VC++ 6.0. I do believe it works in GNU C/C++ and MAC CodeWarrior.

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read