HighTechTalks DotNet Forums  

IDispatch* , COM Server(LOCAL_SERVER), event data and C#.NET

Dotnet Framework (Interop) microsoft.public.dotnet.framework.interop


Discuss IDispatch* , COM Server(LOCAL_SERVER), event data and C#.NET in the Dotnet Framework (Interop) forum.



Reply
 
Thread Tools Search this Thread Display Modes
  #1  
Old   
Debasish Bose, Oracle Corp
 
Posts: n/a

Default IDispatch* , COM Server(LOCAL_SERVER), event data and C#.NET - 12-17-2007 , 02:11 PM






I wrote and maintain a high-performance COM server written in MFC (ATL guys
excuse me), to provide a COM layer on top of an existing SIP protocol stack
written in pure C. I have one main inbound interface called

_ISipPhone and corresponding outbound event interface called
_ISipEventCallback. Both are dispinterfaces. Event and APIs are working fine
up untill now when I intended to pass some structured data (event args)
accross. My intention is to use something like,



[ uuid(FA1A568E-EC16-4af4-8C7F-BD448057622F) ]

dispinterface _ISipEventCallback

{

properties:

// NOTE - ClassWizard will maintain property information here.

// Use extreme caution when editing this section.

//{{AFX_ODL_PROP(CSipEventCallback)

//}}AFX_ODL_PROP


methods:

// NOTE - ClassWizard will maintain method information here.

// Use extreme caution when editing this section.

//{{AFX_ODL_METHOD(CSipEventCallback)

//}}AFX_ODL_METHOD


[

id(1),

helpstring("method OnCallEvent")

]

HRESULT OnCallEvent(ccc_call_id iCallId,

ccc_line hLine,

sip_callstate_event event,

sip_callstate_cause cause,

BSTR bstrRemoteParty,

IDispatch* info);

//SAFEARRAY(VARIANT)* info);//IDispatch* Info);



};



Now first question is



1. what should ideally be passed as event args accross the proces? My client
is C#.



If IDispatch is the answer, I already did the following,



[ uuid(BC494DC1-B538-47ac-AC0F-BCC1BA3B63F7)]

interface _ICallInfo : IDispatch

{

[

propget,

id(1),

helpstring("Call ID")

]

HRESULT CallId([out, retval] LONG *pVal);


};



And the CoClass



[ uuid(AEC6F3D2-C579-49e5-82B9-E4934D708A0A)]

coclass CallInfo

{

[default] dispinterface _ICallInfo;

};



I tried passing IDispatch pointer for this interface impl. as the 6th
parameter of above event -



HRESULT OnCallEvent(ccc_call_id iCallId,

ccc_line hLine,

sip_callstate_event event,

sip_callstate_cause cause,

BSTR bstrRemoteParty,

IDispatch* info);



I did code following C++ wrapper class for the _ICallInfo impl.



class CCallInfo : public CCmdTarget

{

DECLARE_DYNCREATE(CCallInfo)

CCallInfo(); // protected constructor used by dynamic creation

// Attributes

public:

LONG CallId;



// Implementation

protected:

virtual ~CCallInfo();

// Generated message map functions

//{{AFX_MSG(CCallInfo)

// NOTE - the ClassWizard will add and remove member functions here.

//}}AFX_MSG

DECLARE_MESSAGE_MAP()

DECLARE_OLECREATE(CCallInfo)

// Generated OLE dispatch map functions

//{{AFX_DISPATCH(CCallInfo)

//}}AFX_DISPATCH

DECLARE_DISPATCH_MAP()

DECLARE_INTERFACE_MAP()


enum

{

dispidCallId = 1L

};

};



The code for the source file is as below:



IMPLEMENT_DYNCREATE(CCallInfo, CCmdTarget)



CCallInfo::CCallInfo() {

EnableAutomation();


// To keep the application running as long as an OLE automation

// object is active, the constructor calls AfxOleLockApp.


AfxOleLockApp();

}



CCallInfo::~CCallInfo() {

// To terminate the application when all objects created with

// with OLE automation, the destructor calls AfxOleUnlockApp.


AfxOleUnlockApp();

}



void CCallInfo::OnFinalRelease() {

// When the last reference for an automation object is released

// OnFinalRelease is called. The base class will automatically

// deletes the object. Add additional cleanup required for your

// object before calling the base class.

CCmdTarget::OnFinalRelease();

}



BEGIN_MESSAGE_MAP(CCallInfo, CCmdTarget)

//{{AFX_MSG_MAP(CCallInfo)

// NOTE - the ClassWizard will add and remove mapping macros here.

//}}AFX_MSG_MAP

END_MESSAGE_MAP()

BEGIN_DISPATCH_MAP(CCallInfo, CCmdTarget)

//{{AFX_DISPATCH_MAP(CCallInfo)

//}}AFX_DISPATCH_MAP

DISP_PROPERTY_ID(CCallInfo, "CallId", dispidCallId, CallId, VT_I4)

END_DISPATCH_MAP()

//

// Note:

// we add support for IID_ICallInfo to support typesafe binding

// from VBA. This IID must match the GUID that is attached to the

// dispinterface in the .ODL file.



//

// _ICallInfo GUID {BC494DC1-B538-47ac-AC0F-BCC1BA3B63F7}

static const IID IID_ICallInfo =

{ 0xbc494dc1, 0xb538, 0x47ac, { 0xac, 0x0f, 0xbc, 0xc1, 0xba, 0x3b, 0x63,
0xf7 } };

BEGIN_INTERFACE_MAP(CCallInfo, CCmdTarget)

INTERFACE_PART(CCallInfo, IID_ICallInfo, Dispatch)

END_INTERFACE_MAP()

//

// CallInfo CoClass GUID {AEC6F3D2-C579-49e5-82B9-E4934D708A0A}

IMPLEMENT_OLECREATE(CCallInfo, "SipServer.CallInfo", 0xaec6f3d2, 0xc579,
0x49e5, 0x82, 0xb9, 0xe4, 0x93, 0x4d, 0x70, 0x8a, 0x0a)



The calling code is shown below:


static BYTE paramInfo[] = VTS_UI4 VTS_UI4 VTS_I4 VTS_I4 VTS_BSTR
VTS_DISPATCH;//VTS_VARIANT; //VTS_DISPATCH;


CCallInfo* callIno = new CCallInfo();

callIno->CallId = 45;

LPDISPATCH lpdispCallInfo = callIno->GetIDispatch(FALSE);

if ((callIno == NULL) || (lpdispCallInfo == NULL))

{

AfxMessageBox(CString("CallInfo NULL"));

}



// Retrieve the array of connected interfaces from the connection point

const CPtrArray* pConnections = m_xSipServerEvents.GetConnections();

ASSERT(pConnections != NULL);


// Iterate through array, calling the event on each interface

int cConnections = pConnections->GetSize();

COleDispatchDriver sipxEvent;

for (int i = 0; i < cConnections; i++)

{

if((IDispatch*)pConnections->GetAt(i))

{

sipxEvent.AttachDispatch((IDispatch*)pConnections->GetAt(i), false);


try

{

//OnCallEvent()

sipxEvent.InvokeHelper(0x1,

DISPATCH_METHOD,

VT_EMPTY,

NULL,

paramInfo, //param info types: VTS_...

hCall,

hLine,
event,

cause,

_ConvertStringToBSTR (pszRemoteParty),

lpdispCallInfo);

//vaPacket);

}

catch(COleException* ex)

{

#ifdef _DEBUG

AfxMessageBox(CString("Error :" + ex->ReportError()));

#endif

}


catch(...)

{

}


sipxEvent.DetachDispatch();

}

}



At the C# side my event handler (which was working earlier ) looks like



m_sipPhone.OnCallEvent += new
_ISipEventCallback_OnCallEventEventHandler(OnCallE vent);



void OnCallEvent(int hCall,

int hLine,

sip_callstate_event cevent,

sip_callstate_cause cause,

string strRemoteParty,

object callInfo)

//ref object[] callInfo)

{

//...


}



My intention is to access the properties of _ICallInfo interface like



// int call_id = callInfo.CallId; //(int) pVarResult[0];



At first event was not firing at all just after I put IDispatch* in
OnCallEvent's 6th parameter. Now though event is firing but the object I got
in my handler is of type generic COM object or System.__ComObject.



Am I doing it correctly?


Reply With Quote
Reply




Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off



Powered by vBulletin Version 3.5.4
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.