?
Solved

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

Posted on 2006-04-07
14
Medium Priority
?
2,959 Views
Last Modified: 2013-12-14
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.
0
Comment
Question by:Xtreem
  • 6
  • 4
  • 2
12 Comments
 
LVL 8

Expert Comment

by:mrblue
ID: 16428328
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.
0
 

Author Comment

by:Xtreem
ID: 16428586
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.
0
 
LVL 8

Expert Comment

by:mrblue
ID: 16428946
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".




0
What is SQL Server and how does it work?

The purpose of this paper is to provide you background on SQL Server. It’s your self-study guide for learning fundamentals. It includes both the history of SQL and its technical basics. Concepts and definitions will form the solid foundation of your future DBA expertise.

 

Author Comment

by:Xtreem
ID: 16434284
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:
http://www.experts-exchange.com/Programming/Programming_Languages/Cplusplus/Q_21451062.html

This is why I suggested the solution may lie with the COM_INTERFACE_ENTRY2 macro or cast operators...
0
 
LVL 8

Expert Comment

by:mrblue
ID: 16434706
"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
0
 

Author Comment

by:Xtreem
ID: 16434803
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:
http://www.experts-exchange.com/Programming/Programming_Languages/Cplusplus/Q_21771199.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)?
0
 
LVL 8

Accepted Solution

by:
mrblue earned 2000 total points
ID: 16438945
Maybe the reason is to avoid such problems when something was not designed (as I guess) for some purpose :)
The problem lies exactly here:
pmyClass1 = pmyClass2;
it is in operator=() which calls AtlComPtrAssign(IUnknown **pp, IUnknown *p)
Anyway, honestly if there's solution to this problem I simply don't know it, sorry.
I even tried COM_INTERFACE_ENTRY2(IUnknown, ISomeInterface) but it didn't helped. I think it is used rather in QueryInterface() implementation to avoid such ambiguity.
0
 

Author Comment

by:Xtreem
ID: 16606628
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.
0
 
LVL 20

Expert Comment

by:Venabili
ID: 16606756
Noone will help you further if you just ignore an expert comment... One simple "Does not work" would be enough
0
 

Author Comment

by:Xtreem
ID: 16606878
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.
0
 
LVL 20

Expert Comment

by:Venabili
ID: 16607080
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. :)
0
 

Author Comment

by:Xtreem
ID: 16607155
Ok, then I'll let this go through Cleanup using your recommendation.
0

Featured Post

Upgrade your Question Security!

Add Premium security features to your question to ensure its privacy or anonymity. Learn more about your ability to control Question Security today.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

After several hours of googling I could not gather any information on this topic. There are several ways of controlling the USB port connected to any storage device. The best example of that is by changing the registry value of "HKEY_LOCAL_MACHINE\S…
For most people, the WrapPanel seems like a magic when they switch from WinForms to WPF. Most of us will think that the code that is used to write a control like that would be difficult. However, most of the work is done by the WPF engine, and the W…
The viewer will learn how to synchronize PHP projects with a remote server in NetBeans IDE 8.0 for Windows.
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.

864 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question