Passing callbacks from a C# COM server to a C++ COM client

D

dev

After managing to get COM calls working from my existing C++ COM
client to my new C# COM server (see other thread), I was in the
position where callbacks were not triggering. I've managed to get one
working now, but I'm not happy with the solution, and was wondering if
anyone can shed any light on a better solution :

I created simple versions of my server and client so I could post the
code. My C# COM server has an interface called IClass1 and a callback
interface called IClass1_Events.

My original C++ COM client code looked like this :

// Initialise Callbacks
CComObject<CCPPTestClientEvents>* pEvents;
CComObject<CCPPTestClientEvents>::CreateInstance( &pEvents );
m_dwAdvise = 0;
hRes = AtlAdvise( m_pTapi, pEvents->GetUnknown(),
DIID_IClass1_Events, &m_dwAdvise );

where the callback class is simply defined as :

class CCPPTestClientEvents : public IClass1_Events
{
void TheEvent( BSTR bsMsg );
};

but using this with the new COM server resulted in the callback events
never being triggered, and when running in debug mode I could see that
first-chance exceptions being thrown. I read that AtlAdvise wouldn't
work in my situation, so I re-wrote the code as to find the container
and the connection point :

//hRes = AtlAdvise( m_pTapi, pEvents->GetUnknown(),
DIID_IClass1_Events, &m_dwAdvise );
LPCONNECTIONPOINTCONTAINER pContainer;
hr = m_pClass1->QueryInterface(IID_IConnectionPointContainer,
(LPVOID*)&pContainer);
if ( pContainer )
{
hr = pContainer->FindConnectionPoint(DIID_IClass1_Events, &m_pCP);
hr = m_pCP->Advise((LPUNKNOWN)pEvents, &m_dwAdvise);
pContainer->Release();
}

but this didn't seem to make any difference.

I then found another online article, which didn't use a COM smart
pointer at all :

CCPPTestClientEvents m_oEvents;
.....
hr = m_pCP->Advise((LPUNKNOWN)&m_oEvents, &m_dwAdvise);

and for this to work, my callback class (CCPPTestClientEvents) had to
implement the functions QueryInterface, AddRef, Release and Invoke.
This seems to mean that Invoke needs to contain a switch statement to
handle all of my callback functions :

virtual HRESULT _stdcall Invoke(DISPID dispIdMember, REFIID riid,
LCID lcid, WORD wFlags,
DISPPARAMS *pDispParams, VARIANT
*pVarResult,
EXCEPINFO *pExcepInfo, UINT
*puArgErr)
{
switch(dispIdMember)
{
case 1L:
{
//Parameters
_bstr_t strMsg = pDispParams->rgvarg[0].bstrVal;
TheEvent(strMsg);
break;
}
}
return S_OK;
}

and this seems to work !!!! I get the event triggered correctly (and
no exceptions thrown).

However, this is fine for this small example with a single callback
function taking one parameter, but is going to be a pain for the full
version with multiple functions taking multiple parameters. Is there
a short-cut round this, or some way of automatically generating
invoke ?

Or .... have I just made life hard for myself ?

- Tim Dale
 
D

dev

Sorry, just to clarify, in the situation that ISN'T working, where I'm
using a COM smart pointer,
the class definition is :

class CCPPTestClientEvents : public IDispatchImpl<IClass1_Events,
&DIID_IClass1_Events, &CLSID_Class1>, public CComObjectRoot
{
public:
ULONG refCount;
CCPPTestClientEvents() { refCount = 1; }
~CCPPTestClientEvents() {}

BEGIN_COM_MAP(CCPPTestClientEvents)
COM_INTERFACE_ENTRY(IDispatch)
COM_INTERFACE_ENTRY(IClass1_Events)
END_COM_MAP()

void TheEvent( BSTR bsMsg );
};

and this is the method that has always worked with an unmanaged C++
COM server DLL,
with with the new C# managed DLL, I get no events and exceptions
instead.

But if get rid of the COM MAP stuff, implement QueryInterface, AddRef,
Invoke, etc. manually,
create an instance of the class, and pass a reference to that instance
to Advise, it works !
Can anyone explain why, and which is the best way of working ?

(Annoyingly, we also have a VB client, and that will just work
whatever you do.)

- Tim
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top