Link to home
Start Free TrialLog in
Avatar of Xtreem
XtreemFlag for United Kingdom of Great Britain and Northern Ireland

asked on

ATL - Compiler error C2594 (ambiguous conversions from/to IUnknown) when assigning to coclass smart pointer (CComPtr) - multiple inheritance of IUnknown

I have a coclass CMyClass with the inheritance list as shown below:

   class ATL_NO_VTABLE CMyClass :
      public CComObjectRootEx<CComObjectThreadModel>,
      public CComCoClass<CMyClass, &CLSID_MyClass>,
      public IDispatchImpl<IMyClass, &IID_IMyClass, &LIBID_MYLib>,
      public ISupportErrorInfo,
      public IConnectionPointContainerImpl<CMyClass>
   {
      DECLARE_GET_CONTROLLING_UNKNOWN()
      DECLARE_PROTECT_FINAL_CONSTRUCT()

      BEGIN_COM_MAP(CMyClass)
         COM_INTERFACE_ENTRY(IMyClass)
         COM_INTERFACE_ENTRY(IDispatch)
         COM_INTERFACE_ENTRY(ISupportErrorInfo)
         COM_INTERFACE_ENTRY(IConnectionPointContainer)
      END_COM_MAP()
      BEGIN_CONNECTION_POINT_MAP(CMyClass)
      END_CONNECTION_POINT_MAP()

      // ... Plus all other stuff here
   }


However, I'm getting a problem with the following code:

   CComPtr<CMyClass> pmyClass1;
   CComPtr<CMyClass> pmyClass2;
   pmyClass1 = pmyClass2;


I get the following compiler errors:

   atlbase.h(483) : error C2594: 'argument' : ambiguous conversions from 'class CMyClass *const ' to 'struct IUnknown *'
        atlbase.h(482) : while compiling class-template member function 'class CMyClass *__thiscall ATL::CComPtr<class CMyClass>::operator =(const class ATL::CComPtr<class CMyClass> &)'

   atlbase.h(483) : error C2594: 'type cast' : ambiguous conversions from 'struct IUnknown *' to 'class CMyClass *'
        atlbase.h(482) : while compiling class-template member function 'class CMyClass *__thiscall ATL::CComPtr<class CMyClass>::operator =(const class ATL::CComPtr<class CMyClass> &)'


Any idea how to resolve this error? I know this is obviously due to IUnknown being on multiple inheritance branches. Do I need to use COM_INTERFACE_ENTRY2 macro or cast operators perhaps? Only restriction I have is I MUST template my smart pointers to the coclasses rather than the interfaces.
Avatar of Dariusz Dziara
Dariusz Dziara
Flag of Poland image

Parameter for CComPtr template should be COM interface (inherits from IUnknown).
For example you should use:
CComPtr<IMyClass> pIMyClass1;

The way of object creation from C++ class is described in MSDN and depends on ATL version.
Avatar of Xtreem

ASKER

Please see the last sentence of my Question. I MUST template my smart pointers to the coclasses rather than the interfaces. Reason for this is to be able to access __cdecl functions on the COM object.  And I am led to believe it is quite ok to use CComPtr with coclasses (not just interfaces) as CComPtr is for any COM component and coclasses are COM components.
MSDN states for CComPtr:
"T - A COM interface specifying the type of pointer stored"

CComPtr implements for example QueryInterface() method which is simply implemented by calling wrapped interface QueryInterface() method.

"atlbase.h(483) : error C2594: 'argument' : ambiguous conversions from 'class CMyClass *const ' to 'struct IUnknown *' "

It means that CMyClass inherits more than one time IUnknown interface because
IMyClass, ISupportErrorInfo,  IConnectionPointContainerImpl all inherits from IUnknown.

To access __cdecl functions on the COM object you could simply cast interface type onto CMyClass * but in some cases it can be dangerous (when some ATL debugging macroes are used you will not have directly pointer to object but pointer to some proxy object).
I think that better idea is to implement some additional (auxiliary) interface that simply wraps your "__cdecl functions".




Avatar of Xtreem

ASKER

Ok, the restriction I stated remains true, so whether or not it is better to use interface rather than coclass, I cannot change this (this is a work situation). The problem at hand is, as you rightly said, that there is multiple inheritance of IUnknown, which I stated in the Question.

This Question discusses a similar problem, but I don't know if the solution lies therein:
https://www.experts-exchange.com/questions/21451062/ambiguous-conversions-from-'class-ATL-CComObject-class-CTstConnect-'-to-'struct-IUnknown-'.html

This is why I suggested the solution may lie with the COM_INTERFACE_ENTRY2 macro or cast operators...
"Ok, the restriction I stated remains true" ?
I do not understand it clearly. Do you
1) need to declare
CComPtr<CMyClass> pmyClass1;
what I am convinced is incorrect 'cause CMyClass is not an interface ?
2) need to call __cdecl functions
in this case you can declare
CComPtr<IMyClass> pIMyClass1;
and then cast it
CMyClass *pMyClass = (CMyClass *)(IMyClass *)pIMyClass1;
However it won't work if you enable reference count debugging by defining
_ATL_DEBUG_INTERFACES
Avatar of Xtreem

ASKER

The reason is 2) - I need to call __cdecl functions. But the reason I said I am led to believe it is quite ok to use CComPtr with coclasses (not just interfaces) is due to the responses to a previous recent Question I asked:
https://www.experts-exchange.com/questions/21771199/Use-of-CComPtr-smart-pointer-on-coclass-pointer-vs-interface-pointer-in-exception-throwing-situation.html

I would like to put this to my team at work as it was decided that we should use coclass smart pointers (as opposed to interface smart pointers) in order to access __cdecl functions. I just tried your double casting of the interface smart pointer to a coclass pointer in our code and it worked. But is there a good reason we should do this instead of using coclass smart pointers (so I can put this to my team)?
ASKER CERTIFIED SOLUTION
Avatar of Dariusz Dziara
Dariusz Dziara
Flag of Poland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Xtreem

ASKER

mrblue's Answers didn't resolve the problem, so please either close and refund or (preferably) leave the Question open a while longer to see if anyone else comes back with a solution.

Thanks.
Noone will help you further if you just ignore an expert comment... One simple "Does not work" would be enough
Avatar of Xtreem

ASKER

I replied to mrblue last on 04/12/2006 12:00PM BST with the reasoning behind why his possible Answer(s) wouldn't solve my particular problem. mrblue's latest comment on 04/12/2006 07:25PM BST, if you read it, is not another solution, but rather a clarification of why I have the problem in the first place.

To quote mrblue, "honestly if there's solution to this problem I simply don't know it, sorry" and "I even tried COM_INTERFACE_ENTRY2(IUnknown, ISomeInterface) but it didn't helped".

So saying "Does not work" to this would make no sense as it wasn't a solution. If you mean to say I must reply to all expert comments, regardless of what they're commenting about, then I apologise.
I had to type all that I thought...
I do not know of a solution either. In fact I do not really believe that there is a solution and the last comment is a pretty good explanation why it is like this- that is why I recommend award :)

What I was saying is that it is better if you can reply to all experts - this way the next person that opens the question will see that you care. :)
Avatar of Xtreem

ASKER

Ok, then I'll let this go through Cleanup using your recommendation.