Xtreem
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<CComObjec tThreadMod el>,
public CComCoClass<CMyClass, &CLSID_MyClass>,
public IDispatchImpl<IMyClass, &IID_IMyClass, &LIBID_MYLib>,
public ISupportErrorInfo,
public IConnectionPointContainerI mpl<CMyCla ss>
{
DECLARE_GET_CONTROLLING_UN KNOWN()
DECLARE_PROTECT_FINAL_CONS TRUCT()
BEGIN_COM_MAP(CMyClass)
COM_INTERFACE_ENTRY(IMyCla ss)
COM_INTERFACE_ENTRY(IDispa tch)
COM_INTERFACE_ENTRY(ISuppo rtErrorInf o)
COM_INTERFACE_ENTRY(IConne ctionPoint Container)
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.
class ATL_NO_VTABLE CMyClass :
public CComObjectRootEx<CComObjec
public CComCoClass<CMyClass, &CLSID_MyClass>,
public IDispatchImpl<IMyClass, &IID_IMyClass, &LIBID_MYLib>,
public ISupportErrorInfo,
public IConnectionPointContainerI
{
DECLARE_GET_CONTROLLING_UN
DECLARE_PROTECT_FINAL_CONS
BEGIN_COM_MAP(CMyClass)
COM_INTERFACE_ENTRY(IMyCla
COM_INTERFACE_ENTRY(IDispa
COM_INTERFACE_ENTRY(ISuppo
COM_INTERFACE_ENTRY(IConne
END_COM_MAP()
BEGIN_CONNECTION_POINT_MAP
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.
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, IConnectionPointContainerI mpl 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".
"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, IConnectionPointContainerI
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".
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...
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
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
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)?
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
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
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.
Thanks.
Noone will help you further if you just ignore an expert comment... One simple "Does not work" would be enough
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(IUnkn own, 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.
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(IUnkn
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. :)
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. :)
ASKER
Ok, then I'll let this go through Cleanup using your recommendation.
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.