Sign in to follow this  
DeafManNoEars

COM Smart Pointers

Recommended Posts

Are there any good COM smart pointer implementations. I am using C++, and VS8 Express. I am trying to use CComPtr in <Atlbase.h> to no avail. These are the compiler errors.
C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\atlmfc\include\atlcomcli.h(300) : error C2299: 'ATL::CComPtr<T>::operator =' : behavior change: an explicit specialization cannot be a copy constructor or copy assignment operator
        C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\atlmfc\include\atlcomcli.h(304) : see reference to class template instantiation 'ATL::CComPtr<T>' being compiled
C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\atlmfc\include\atlcomcli.h(300) : error C2299: 'ATL::CComPtr<T>::operator =' : behavior change: an explicit specialization cannot be a copy constructor or copy assignment operator
        with
        [
            T=IUnknown
        ]
        C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\atlmfc\include\atlcomcli.h(508) : see reference to class template instantiation 'ATL::CComPtr<T>' being compiled
        with
        [
            T=IUnknown
        ]
C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\atlmfc\include\atlcomcli.h(300) : error C2299: 'ATL::CComPtr<T>::operator =' : behavior change: an explicit specialization cannot be a copy constructor or copy assignment operator
        with
        [
            T=IPersistStream
        ]
        C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\atlmfc\include\atlcomcli.h(2215) : see reference to class template instantiation 'ATL::CComPtr<T>' being compiled
        with
        [
            T=IPersistStream
        ]
C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\atlmfc\include\atlbase.h(861) : error C2299: 'ATL::CAutoPtr<T>::CAutoPtr' : behavior change: an explicit specialization cannot be a copy constructor or copy assignment operator
        C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\atlmfc\include\atlbase.h(927) : see reference to class template instantiation 'ATL::CAutoPtr<T>' being compiled
C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\atlmfc\include\atlbase.h(884) : error C2299: 'ATL::CAutoPtr<T>::operator =' : behavior change: an explicit specialization cannot be a copy constructor or copy assignment operator
C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\atlmfc\include\atlbase.h(4522) : error C3203: 'CComAutoThreadModule' : unspecialized class template can't be used as a template argument for template parameter 'T', expected a real type
        C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\atlmfc\include\atlbase.h(4534) : see reference to class template instantiation 'ATL::CComAutoThreadModule<ThreadAllocator,dwWait>' being compiled
C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\atlmfc\include\atlcomcli.h(300) : error C2299: 'ATL::CComPtr<T>::operator =' : behavior change: an explicit specialization cannot be a copy constructor or copy assignment operator
        with
        [
            T=ITypeLib
        ]
        C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\atlmfc\include\atlbase.h(5982) : see reference to class template instantiation 'ATL::CComPtr<T>' being compiled
        with
        [
            T=ITypeLib
        ]
C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\atlmfc\include\atlcomcli.h(300) : error C2299: 'ATL::CComPtr<T>::operator =' : behavior change: an explicit specialization cannot be a copy constructor or copy assignment operator
        with
        [
            T=ICatRegister
        ]
        C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\atlmfc\include\atlbase.h(6100) : see reference to class template instantiation 'ATL::CComPtr<T>' being compiled
        with
        [
            T=ICatRegister
        ]
C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\atlmfc\include\atlcomcli.h(300) : error C2299: 'ATL::CComPtr<T>::operator =' : behavior change: an explicit specialization cannot be a copy constructor or copy assignment operator
        with
        [
            T=LPD3DXMESH
        ]
        c:\documents and settings\running\my documents\visual studio projects\yardville\source\../include/Renderdata.h(17) : see reference to class template instantiation 'ATL::CComPtr<T>' being compiled
        with
        [
            T=LPD3DXMESH
        ]



any ideas??!?? Not me... ------------------------------------------------------ So I started working on my own, but I would rather work with something more tested. Also, I am running into issues with the implementation; I cannot AddRef () to a COM object that I haven't yet acquired. So do I add an Acquire() method that will set a flag, such that while this flag is set, I need to call AddRef() next time I access the COM object before I reset the flag, however if the Com_ptr is destroyed before the item is released I will not call Release()?
template<class T>
class com_ptr
{
public:
	com_ptr(T* raw):ptr(raw),bRefNeeded(false)
	{
		if (ptr)
			ptr->AddRef();
	}

	com_ptr(const com_ptr<T> &rhs):ptr(rhs.ptr)
	{
		if (ptr)
			ptr->AddRef;
	}

	com_ptr& operator=(const com_ptr& rhs)
	{
		if ( this->ptr == rhs.ptr)
			return *this;

		if (ptr)
			ptr->Release();

		ptr = rhs.ptr; 
                if (ptr)
                        ptr->AddRef();
	}

   ~com_ptr()
   {
	   if (ptr && !bRefNeeded)
		   ptr->Release();
   }

   T* Acquire()
   {
           bRefNeeded = true; // or something of the sort !!!!!
	   return ptr;
   }

   T* Get()
   {
           if (ptr && bRefNeeded)
           {
                 ptr->AddRef();
                 bRefNeeded = false;
           } 

	   return ptr;
   }

   T& operator*() const
   {
      if (ptr && bRefNeeded)
           {
                 ptr->AddRef();
                 bRefNeeded = false;
           } 

      return *ptr;
   }

   T* operator->() const
   {
      if (ptr && bRefNeeded)
           {
                 ptr->AddRef();
                 bRefNeeded = false;
           } 
      return ptr;
   }
private:
   T* ptr;
   bool bRefNeeded;
};



[Edited by - DeafManNoEars on August 13, 2007 9:24:13 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by Sneftel
You can use Boost smart pointers with a custom deleter to hold a reference to a COM object. See the programming techniques page for more info.


I'll look into that, thanks.


Doesn't this kind of kill me if a copy goes out of scope???
Quote:

All pw copies will share a single reference.


Or do you just call make_shared_from_COM for each copy.

Share this post


Link to post
Share on other sites
Quote:
Original post by DeafManNoEars
Doesn't this kind of kill me if a copy goes out of scope???


No, it doesn't (as long as you have other copies of the shared_ptr around). That quote refers to the fact that you are no longer using the internal reference count of the COM objects, but rather the shared_ptr's reference count.

Speaking of which, you might also be interested in using boost::intrusive_ptr with your COM pointers (since that will use the COM reference count):

void intrusive_ptr_add_ref( IUnknown const * const p ) {
p.AddRef();
}

void intrusive_ptr_release( IUnknown const * const p ) {
p.Release();
}

// ...

typedef boost::intrusive_ptr< ID3DXMesh > MeshPtr;
MeshPtr mesh;

{
LPD3DXMESH meshptr = 0;
D3DXCreateMesh( ... );
MeshPtr( meshptr, false ).swap( mesh );
}



jfl.

Share this post


Link to post
Share on other sites
Quote:
Original post by jflanglois
Quote:
Original post by DeafManNoEars
Doesn't this kind of kill me if a copy goes out of scope???


No, it doesn't (as long as you have other copies of the shared_ptr around). That quote refers to the fact that you are no longer using the internal reference count of the COM objects, but rather the shared_ptr's reference count.




OK checked it out and it works perfectly. Thanks for clearing that up.

Share this post


Link to post
Share on other sites
You seem to be using CComPtr with an LPD3DXMESH, which is incorrect-the template parameter should be an interface, not an interface pointer. Instead of CComPtr<LPD3DXMESH>, use CComPtr<ID3DXMesh>. If you get more errors, post the code and the errors.

Share this post


Link to post
Share on other sites
Quote:
Original post by JohnBolton
I used CComPtr a lot a while back and I didn't have any trouble. Post the code generating those errors.


I can't even get this to compile, with errors pointing me to atlcomcli.h.


//file RenderData.h
#include <atlbase.h>

struct ID3DXMesh;

class RenderData
{
public:
RenderData():m_pMesh(){};
~RenderData(){};

private:
CComPtr<ID3DXMesh> m_pMesh;


};





I broke the above out of my project to make sure there wasn't something wrong with the way I was using it or another part of my app. i just try to instantiate a RenderData object on the stack and that's it (like below). It won't compile.


//Test.h
#include "stdafx.h" // "renderdata.h" and <d3dx9.h> in here

int _tmain(int argc, _TCHAR* argv[])
{


return 0;
}





This is my build log.

Compiling...
stdafx.cpp
atlmfc\include\atlcomcli.h(300) : error C2299: 'ATL::CComPtr<T>::operator =' : behavior change: an explicit specialization cannot be a copy constructor or copy assignment operator
atlmfc\include\atlcomcli.h(304) : see reference to class template instantiation 'ATL::CComPtr<T>' being compiled
atlmfc\include\atlcomcli.h(300) : error C2299: 'ATL::CComPtr<T>::operator =' : behavior change: an explicit specialization cannot be a copy constructor or copy assignment operator
with
[
T=IUnknown
]
atlmfc\include\atlcomcli.h(508) : see reference to class template instantiation 'ATL::CComPtr<T>' being compiled
with
[
T=IUnknown
]
atlmfc\include\atlcomcli.h(300) : error C2299: 'ATL::CComPtr<T>::operator =' : behavior change: an explicit specialization cannot be a copy constructor or copy assignment operator
with
[
T=IPersistStream
]
atlmfc\include\atlcomcli.h(2215) : see reference to class template instantiation 'ATL::CComPtr<T>' being compiled
with
[
T=IPersistStream
]
atlmfc\include\atlbase.h(861) : error C2299: 'ATL::CAutoPtr<T>::CAutoPtr' : behavior change: an explicit specialization cannot be a copy constructor or copy assignment operator
atlmfc\include\atlbase.h(927) : see reference to class template instantiation 'ATL::CAutoPtr<T>' being compiled
atlmfc\include\atlbase.h(884) : error C2299: 'ATL::CAutoPtr<T>::operator =' : behavior change: an explicit specialization cannot be a copy constructor or copy assignment operator
atlmfc\include\atlbase.h(4522) : error C3203: 'CComAutoThreadModule' : unspecialized class template can't be used as a template argument for template parameter 'T', expected a real type
atlmfc\include\atlbase.h(4534) : see reference to class template instantiation 'ATL::CComAutoThreadModule<ThreadAllocator,dwWait>' being compiled
atlmfc\include\atlcomcli.h(300) : error C2299: 'ATL::CComPtr<T>::operator =' : behavior change: an explicit specialization cannot be a copy constructor or copy assignment operator
with
[
T=ITypeLib
]

atlmfc\include\atlbase.h(5982) : see reference to class template instantiation 'ATL::CComPtr<T>' being compiled
with
[
T=ITypeLib
]

atlmfc\include\atlcomcli.h(300) : error C2299: 'ATL::CComPtr<T>::operator =' : behavior change: an explicit specialization cannot be a copy constructor or copy assignment operator
with
[
T=ICatRegister
]

atlmfc\include\atlbase.h(6100) : see reference to class template instantiation 'ATL::CComPtr<T>' being compiled
with
[
T=ICatRegister
]


atlmfc\include\atlcomcli.h(300) : error C2299: 'ATL::CComPtr<T>::operator =' : behavior change: an explicit specialization cannot be a copy constructor or copy assignment operator
with
[
T=ID3DXMesh
]





So, an explicit specialization cannot be a copy constructor or copy assignment operator. OK, how do I get around this?

This is not critical as
boost::shared_ptr
appears to do the trick.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this