Click here to Skip to main content
Click here to Skip to main content

A COM Smart Pointer

, 22 Feb 2006
Rate this:
Please Sign up or sign in to vote.
A wrapper class to any COM interface pointer.

Introduction

CComPtr wraps any interface pointer and will call AddRef() and Release() properly. That is, you don't need to worry about controlling the lifetime of your interface pointer.

Details

  1. ATL does provide a Smart Pointer class named CComQIPtr. But it uses some ATL related funtion so that it can be used only in an ATL environment.
  2. VC does provide _com_ptr_t & _bstr_ptr_t keywords to provide some kind of a wrapper. But it depends on the MS VC compiler, without which you can benefit.
  3. My CComPtr provides compiler unrelated features to wrap any interface pointer except IUnknown. Later I will explain why this limitation comes.

Illustration

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

CComPtr has four constructors to meet different requirement.

  • CComPtr()

Simply constructor, do nothing.

  • CComPtr(INTERFACE* lPtr)

Construct a new CComPtr object with an existing interface pointer. After that this new CComPtr object can be used as interface pointer itself.

  • CComPtr(IUnknown* pIUnknown, IID iid)

Construct a new CComPtr object with an IUnknown pointer and an IID, which represents the interface you are interested in. Internally constructor will call pIUnknown->QueryInterface to fetch interface pointer according to the IID.

  • CComPtr(const CComPtr<INTERFACE, piid>& RefComPtr)

This contsructor takes another existing CComPtr object as parameter. After that, clone the old CComPtr object.

CComPtr has one destructor, which will release interface pointer.

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

CComPtr has five operators.

  • (a) Operator INTERFACE* : Returns interface pointer wrapped by class CComPtr.

Example:

CComPtr<IWavePciStream> m_wavePciStreamPtr; 
IWavePciStream* pWavePciStream = (IWavePciStream*)m_wavePciStreamPtr;
  • (b) Operator *: Used to fetch interface object wrapped by class CComPtr.

Example:

CComPtr<IWavePciStream> m_wavePciStreamPtr; 
IWavePciStream wavePciStream = *m_wavePciStreamPtr;
  • (c) Operator &: Used to fetch the pointer to interface pointer wrapped by class CComPtr.

Example:

CComPtr<IWavePciStream> m_wavePciStreamPtr; 
IWavePciStream** ppWavePciStream = &m_wavePciStreamPtr;
  • (d) Operator -> : Used to make CComPtr object act as a TRUE interface pointer.

Example

CComPtr<IWavePciStream> m_wavePciStreamPtr; 
m_wavePciStreamPtr->AnyPciStreamMethods();
  • (e) Operator = : Used to transfer an exsiting interface pointer information to a new CComPtr object. This operator has three different parameter list.
    1. In parameter is INTERFACE*
    2. In parameter is another CComPtr object.
    3. In parameter is an interface pointer to IUnknown, which will be used to query other interface pointer defined by piid.

CComPtr has another three methods.

  • Attach : Used to attach an existing interface pointer to a CComPtr object.
  • Detach : Used to detach interface pointer from a CComPtr object.
  • Release : Used to release 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.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

Skeeter
Program Manager Microsoft
China China
Graduated from Shanghai Tongji university in 1997 with bachelor degree in computer science, Wenbin got his first job as a system engineer at Bell Alcatel Mobile Shanghai office responsible for telcom-class mobile system development and deployment. Since then, Wenbin has in turn worked for Intel and Microsoft both inside and outside China, first as senior engineer, later project manager and then senior product manager.
 
With 15-year experience working with the world top IT companies, Wenbin has developed solid skill in C/C++, C#, Java, software engineering, agile development, etc, and multiple talents in product management, public presentation and speech, etc. He has always been an active member at PMI (Project Management Institution) and a regular lecture at Intel Developer Forum, Microsoft TechED conference as well as many other world-class industrial conferences. His wide-ranged industrial practice and high-level personal maturity have made him one of the best in public speech and professional training.
 
Over the years, Wenbin has cultivated his very own style in public speech, which is considered informative, engaging and refined. Since last year, Wenbin has also taken new adventure in project and product management consulting business and has proven high capacity through his work with many local emergent IT firms. Wenbin’s specialty in management consulting is on project management methodologies and processes, project management tools (e.g. MS Project), and team recruitment, build, and motivation.
 
In addition, Wenbin has received many professional qualifications including MCSE (Microsoft Certified System Engineer), MCSD (Microsoft Certified System Developer), MCDBA (Microsoft Certified Database Administrator), SCJP 2 (Sun Certified Java Programmer 2), and PMP (PMI Certified Project Management Professional). On top of that, Wenbin has got several on-duty inventions and one of them was successfully patented by United States Patent and Trademark Office.

Comments and Discussions

 
GeneralThis is buggy and in efficient as hell Pinmembergoldsam28-Oct-05 7:46 
This class is horribly flawed in logic as well as inefficient.
 
Consider the IsEqualObject(IUnknown* pOther) method:
First, there is no need to check if both are NULL.. they either equal each other or they don't. It doesn't make sense to compare the interfaces after a call to QueryInterface with IID = IID_IUnknown. m_Ptr is the interface already being held, so IT MUST BE AN IUnknown. The same goes with pOther... you already know all COM interfaces have IUnknown as a base... thats not what QueryInterface was designed to discover. YOU COULDN'T CALL QueryInterface IF THEY DIDN'T SUPPORT IT!! In addition to that total brain dead logic, you are leaking memory!!! you are only calling Release() on the interfaces if both point to an object, what happens if only one of the QueryInterface calls is succesful?
 
You also seem to have some obsession of setting m_Ptr to 0 in the most pointless places. Here is one of many tasty examples of your zeroing fetish:
 
CComPtr(const CComPtr& RefComPtr)
{
m_Ptr = NULL; <----------- WHY?!
m_Ptr = (INTERFACE*)RefComPtr; <----- this gonna be zero... or have a value
if (m_Ptr)
{
m_Ptr->AddRef();
}
}
 
In the future, you should really take the time to review you're code before you post it to a site like this. The inefficiencies are minor, buy the memory leak issue is hard to miss. Just slow down a bit.
 
-- modified at 13:46 Friday 28th October, 2005
GeneralRe: This is buggy and in efficient as hell PinmemberSkeeter21-Feb-06 11:08 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web04 | 2.8.140821.2 | Last Updated 22 Feb 2006
Article Copyright 2001 by Skeeter
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid