Should I be using CComptr , boost::share_ptr, or boost::intrusive_ptr for COM

Started by
16 comments, last by iMalc 14 years, 4 months ago
Quote:Original post by iMalc
Quote:Original post by ApochPiQ
Yes, but the point is, you have to do extra work to make intrusive_ptr work correctly with COM's reference counting system. Can you at all justify doing that over using the CComPtr class which is already guaranteed to do the correct thing?
Indeed. "Can" does not equal "should".


"Should" equals "should" though. Can you really justify not only creating a dependency on an ENTIRE LIBRARY for a single class, but also littering your codebase with a horrendously dangerous function call, when there is an alternative that has 100% of the benefits of CComPtr, with none of the negatives?
Advertisement
Oh, I didn't see your QueryInterface adapter there - nice touch.

Well each to his own then I guess.
"In order to understand recursion, you must first understand recursion."
My website dedicated to sorting algorithms
Honestly if it weren't for operator& I'd use it. I can stomach making a dependency on ATL. But what happens when you store CComPtr in a container? I don't even think you can actually, because STL, and for that matter, pretty much anything depends on operator& behaving a certain way. operator& doesn't even return the same type, so if you have a vector<CComPtr<IUnknown> > then there's no way to operate on this generically, and for that matter it might not even compile. If it does compile, you're in for a world of hurt, and that's just one container.

Relying on anything that uses operator& should be banned by virtually all reasonable coding standards IMO. This is the type of bug that if you do ever run into, it will take you days, if not weeks to figure out
I prefer CComPtr, if I have the option. You just have to watch out for the assignment operator...a lot of noobies use that when they really want Attach (assignment operator will call AddRef, Attach won't).
Quote:Original post by cache_hit
Quote:Original post by ApochPiQ
Can you at all justify doing that over using the CComPtr class which is already guaranteed to do the correct thing?


Absolutely.



Fair enough [smile]

I must admit that my last experience with COM and C++ was in a shop stuck in the mid '90s, writing MFC and ATL code all over the place; in that context I often saw people doing (unsafe) manual reference counting on their COM pointers, and lots of bugs as a result. From that perspective, using CComPtr was "the right thing to do" as far as writing mostly correct code. Worse, that shop was behind the curve on VS releases for a long time, and still used VC++6.0, which obviously couldn't cope with most of boost anyways, so the applicability of boost to the project was a moot point.

Since then I've been careful to only touch COM in managed languages, which is a far better way to go about things [smile]


So I guess my instincts are out of date on that issue. Should I ever find myself having to do COM work in C++ again (God forbid!) I'll definitely be looking for something like cache_hit's code.

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]

As far as I know, the latest answer to COM pointers in ATL are _com_ptr_t (and _bstr_t, _variant_t). This is also the pointer that's used for the ISomeInterfacePtr typedefs when you #import a COM DLL (#import is a Microsoft extension to VC++).

They work well in STL containers and you even get a clean solution for QueryInterface:

_COM_SMARTPTR_TYPEDEF(ISomething, IID_ISomething);_COM_SMARTPTR_TYPEDEF(IOther, IID_IOther);    // Create a new instance using CoCreateInstance()ISomethingPtr something = ISomethingPtr(CLSID_Something);// QueryInterface to another IIDtry {  IOtherPtr other = something;}catch(const _com_error &error) {  cerr << "QueryInterface failed with HRESULT = " << error.Error();}

Or assign new instances easily:

template<typename Class>inline CComObject<Class> *com_new() {  CComObject<Class> *pInstance;  CheckError(CComObject<Class>::CreateInstance(&pInstance));  return pInstance;}// Create an instance of a local ATL classISomethingPtr something = com_new<CSomeAtlCoClass>();// Take out the pointer without Release()ingISomething *raw = something.Detach();// Assign a new pointer without AddRef()ingsomething.Attach(new ManuallyImplementedCoClass());

Earlier DirectX SDKs also declared _com_ptr_ts for you if you #included <comdef.h> before d3d9.h, but I believe this is no longer the case.

Personally, I'd stay away from CComPtr, CComBSTR and their companions. Compare the code behind CComPtr and _com_ptr_t and the choice should be rather clear.
Professional C++ and .NET developer trying to break into indie game development.
Follow my progress: http://blog.nuclex-games.com/ or Twitter - Topics: Ogre3D, Blender, game architecture tips & code snippets.
I'll have to look into the solution about _com_ptr_t, _bstr_t, etc. To be honest I'm not very familiar with them. I suppose if I had to remove the library dependency I could copy them out in theory.

Still though, I think I would miss the ability to write things like:

d3d->CreateDevice(..., take_ptr(device));

The only alternatives are either an overloaded address-of operator or an additional line of code to first store it in a raw pointer.
Quote:Original post by Cygon
As far as I know, the latest answer to COM pointers in ATL are _com_ptr_t (and _bstr_t, _variant_t). This is also the pointer that's used for the ISomeInterfacePtr typedefs when you #import a COM DLL (#import is a Microsoft extension to VC++).

They work well in STL containers and you even get a clean solution for QueryInterface:
Ah actually I'm all too familiar with those as well. The problem is that even the VS2008 implementation of them misses some consts in it. For example the less-than operator uses the one parameter version and although it takes that parameter by const reference, the method itself isn't const. This causes much difficulty when trying to store a std::set of these etc.

The address-of operator of a CComPtr can be worked around by wrapping them in a CAdapt.
Wrapping an ISomethingPtr pointer in something to correct its bugs is a lot more work.
"In order to understand recursion, you must first understand recursion."
My website dedicated to sorting algorithms

This topic is closed to new replies.

Advertisement