views:

616

answers:

2

I have defined the following CComPtr object and method in my class:

private:

    CComPtr<IRawPdu>& getRawPdu();
    // Returns the RawPdu interface pointer from the mRawPdu data member.
    // mRawPdu is initialized, if necessary.

    CComPtr<IRawPdu> mRawPdu;
    // Initialized to 0 in the ctor.  Uses lazy evaluation via getRawPdu().

In the constructor of my class, I initialise mRawPdu to 0 via the initialisor list. The getRawPdu() method used lazy evaluation if mRawPdu has yet to be initialised.

When compiling the code, I get the following errors:

Compiling...
topport.cpp
C:\Program Files\Microsoft Visual Studio 8\VC\atlmfc\include\atlcomcli.h(295) : error C2664: 'ATL::AtlComPtrAssign' : cannot convert parameter 2 from 'const ATL::CComPtr<T>' to 'IUnknown *'
        with
        [
            T=IRawPdu
        ]
        No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
        C:\Program Files\Microsoft Visual Studio 8\VC\atlmfc\include\atlcomcli.h(292) : while compiling class template member function 'IRawPdu *ATL::CComPtr<T>::operator =(const ATL::CComPtr<T> &) throw()'
        with
        [
            T=IRawPdu
        ]
        sessionutilities.h(186) : see reference to class template instantiation 'ATL::CComPtr<T>' being compiled
        with
        [
            T=IRawPdu
        ]
topglobals.cpp
C:\Program Files\Microsoft Visual Studio 8\VC\atlmfc\include\atlcomcli.h(295) : error C2664: 'ATL::AtlComPtrAssign' : cannot convert parameter 2 from 'const ATL::CComPtr<T>' to 'IUnknown *'
        with
        [
            T=IRawPdu
        ]
        No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
        C:\Program Files\Microsoft Visual Studio 8\VC\atlmfc\include\atlcomcli.h(292) : while compiling class template member function 'IRawPdu *ATL::CComPtr<T>::operator =(const ATL::CComPtr<T> &) throw()'
        with
        [
            T=IRawPdu
        ]
        sessionutilities.h(186) : see reference to class template instantiation 'ATL::CComPtr<T>' being compiled
        with
        [
            T=IRawPdu
        ]

Any suggestions as to what could be causing this?

+1  A: 

Based on the error given by the compiler it appears that it cannot infer a conversion between IRawPdu and IUnknown.

Does it actually inherit from IUnknown? If so then it's possibly an include ordering issue. Can you give more insight into the hierarchy of IRawPdu

JaredPar
IRawPdu inherits from IDispatch which in turn inherits from IUnknown. The weird thing is that this was working fine, but then I moved the mRawPdu object into another class, and only NOW is it failing with these errors. So maybe it is an include ordering issue, but I'm not sure how to isolate it.
LeopardSkinPillBoxHat
I just figured it out - your "include ordering issue" comment was the clue. The problem was that many other .cpp files were including my header file with the CComPtr definition, but the IRawPdu declaration was only being included in the .cpp file where I was using it. I moved the MIDL generated header file which defines the interface into the stdafx.h precompiled header, and it seemed to fix the problem. Thanks for the suggestions!
LeopardSkinPillBoxHat
A: 

Don't pass CComPtr<>'s around since there's no need, just return the pointer to the interface. For example:

  IRawPdu* getRawPdu() { return mRawPdu; }   // Does not add to the reference count

  HRESULT get_RawPdu(IRawPdu** ppPdu)   // Returns RawPdu, but add ref's it.
  {
     return mRawPdu.CopyTo(ppPdu);
  }

  CComPtr<IRawPdu> mRawPdu;
  // Initialized to 0 in the ctor.  Uses lazy evaluation via getRawPdu().

So, when it comes time to use it:

  IRawPdu* pTempRawPdu  = class->getRawPdu();
  // use pTempRawPdu in a temporary manner (since it's not add reffed)

But, better would be:

  CComPtr<IRawPdu> spRawPdu = class->getRawPdu();
  // the ctor of the local CComPtr<> calls AddRef() (and automagically Release's when done)
cmroanirgo