Groups | Blog | Home
all groups > dotnet interop > march 2007 >

dotnet interop : Buffer Overrun when .net event fires to a c++ app


Chris Priest
3/26/2007 12:00:00 AM
Hi,

We are trying to implement COM inside our .NET c# application, that
needs to be called from a C++ app.

While we can get the properties and methods to work just fine, the C++
client has an issue with the events.

The C++ client can see and register interest in the c# event just fine,
I can debug the .net code and see that the C++ has registered interest,
but as soon as the .net app fires the event, the C++ app dies with a
Buffer Overrun exception.

The event has no parameters, I've worked based on the information
available from Microsoft, but I cannot fathom out why this is happening.

Unfortunately I am not a C++ programmer, but a C# programmer, so the C++
code makes little sense!

Does any one have any thoughts on why this might be happening?

The relevant code is shown below:

Interface in .NET DLL:

namespace ClientControl
{
[Guid("04F3C372-9E85-442d-B7E4-D6966E14BD0E")]
[ComVisible(true)]
public interface IClientControl
{
void Login(string serverAddress, int serverPort, string username,
string password);
void Logout();
void Dispose();
void ChangeStatus(string status);
string CurrentStatus { get; }
string Version { get; }
}

[Guid("548B0682-AA8E-437c-839C-877BF9CADE3B")]
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsDual)]
[ComVisible(true)]

public interface IClientControl_Events
{
[DispId(1)]
void StatusChanged();
[DispId(2)]
void Notification();
}

}

Main Class File:

public delegate void StatusChangedEventHandler();
public delegate void NotificationEventHandler();

[ClassInterface(ClassInterfaceType.None),ComSourceInterfaces(typeof(IClientControl_Events))]
[Guid("6612B82C-3C47-4c99-AE5E-FC83C397AF2C")]
[ComVisible(true)]
public partial class ClientControl : UserControl, IClientControl,
IDisposable

public event NotificationEventHandler Notification;
public event StatusChangedEventHandler StatusChanged;

Code to fire event:

if (StatusChanged != null)
{
StatusChanged();
}

If anyone has any pointers, I'd love to hear them!

Best Regards
Chris Priest
3/26/2007 12:00:00 AM
In Addition to the last post:

I get the following when debugging the .net code (using the C++ exe as
the test container for debug)

-----------

ERROR : Unable to load Typelibrary. (HRESULT = 0x8002801d)
Verify TypelibID and major version specified with
IDispatchImpl, CStockPropImpl, IProvideClassInfoImpl or
IProvideCLassInfo2Impl
A first chance exception of type
'System.Runtime.InteropServices.COMException' occurred in ClientControl.dll
An unhandled exception of type
'System.Runtime.InteropServices.COMException' occurred in ClientControl.dll

Additional information: Library not registered. (Exception from HRESULT:
0x8002801D (TYPE_E_LIBNOTREGISTERED))

------------

This occurs as soon as the .net code tries to raise the event.

Regards
Jayme Pechan
3/26/2007 8:36:37 AM
You might look at your C++ event sink class. I suspect your error is
probably in there. Maybe you could show your event sink implementation from
your C++ code here. The C# code looks fine to me.


[quoted text, click to view]

Chris Priest
3/26/2007 5:14:57 PM
Hi Jayme,

I think this is what you are referring to :) :

// ClientControlEventSink.h

#pragma once
#import "ClientControl.tlb" named_guids raw_interfaces_only
#define IDC_ClientControl 998

// CClientControlEventSink command target

class CClientControlEventSink : public CCmdTarget
{
DECLARE_DYNAMIC(CClientControlEventSink)

public:
CClientControlEventSink();
virtual ~CClientControlEventSink();

virtual void OnFinalRelease();

// ClientControl overrides
void OnStatusChanged();

protected:
DECLARE_MESSAGE_MAP()
DECLARE_DISPATCH_MAP()
DECLARE_INTERFACE_MAP()




// ClientControlEventSink.cpp : implementation file
//

#include "stdafx.h"
#include "tryclientcontrol.h"
#include "ClientControlEventSink.h"

// CClientControlEventSink

IMPLEMENT_DYNAMIC(CClientControlEventSink, CCmdTarget)


CClientControlEventSink::CClientControlEventSink()
{
EnableAutomation();
}

CClientControlEventSink::~CClientControlEventSink()
{
}


void CClientControlEventSink::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(CClientControlEventSink, CCmdTarget)
END_MESSAGE_MAP()


BEGIN_DISPATCH_MAP(CClientControlEventSink, CCmdTarget)
DISP_FUNCTION_ID(CClientControlEventSink,"StatusChanged", 0x00000001,
OnStatusChanged,VT_EMPTY,VTS_I4 VTS_I4)
END_DISPATCH_MAP()

// Note: we add support for IID_IClientControlEventSink to support
typesafe binding
// from VBA. This IID must match the GUID that is attached to the
// dispinterface in the .IDL file.

// {6998F069-5D1D-45A3-9E42-384B6C5FA9B1}
//static const IID IID_IClientControlEventSink =
//{ 0x6998F069, 0x5D1D, 0x45A3, { 0x9E, 0x42, 0x38, 0x4B, 0x6C, 0x5F,
0xA9, 0xB1 } };
static const IID IID_IClientControlEventSink =
{ 0x548B0682, 0xAA8E, 0x437C, { 0x83, 0x9C, 0x87, 0x7B, 0xF9, 0xCA,
0xDE, 0x3B } };

BEGIN_INTERFACE_MAP(CClientControlEventSink, CCmdTarget)
INTERFACE_PART(CClientControlEventSink,
ClientControl::DIID_IClientControl_Events, Dispatch)
END_INTERFACE_MAP()


// CClientControlEventSink message handlers
void CClientControlEventSink::OnStatusChanged()
{
int i = 1000;
}





// ATlClientContainer.h : Declaration of the CATlClientContainer

#pragma once

#include "resource.h" // main symbols

#include <atlhost.h>
#include <string>

#import "ClientControl.tlb" named_guids raw_interfaces_only
#define IDC_ClientControl 998

// CATlClientContainer
class CATlClientContainer;
typedef IDispEventImpl<IDC_ClientControl, CATlClientContainer,
&ClientControl::DIID_IClientControl_Events,
&ClientControl::LIBID_ClientControl> VoipIMControlEvent;

class CATlClientContainer :
public CAxDialogImpl<CATlClientContainer>,
public VoipIMControlEvent
{
public:
CATlClientContainer()
{
}

~CATlClientContainer()
{
}

enum { IDD = IDD_ATLCLIENTCONTAINER };

BEGIN_MSG_MAP(CATlClientContainer)
MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
CHAIN_MSG_MAP(CAxDialogImpl<CATlClientContainer>)
END_MSG_MAP()

BEGIN_SINK_MAP(CATlClientContainer)
//Make sure the Event Handlers have __stdcall calling convention
SINK_ENTRY_EX(IDC_ClientControl,
ClientControl::DIID_IClientControl_Events, 0x00000001, StatusChanged)
SINK_ENTRY_EX(IDC_ClientControl,
ClientControl::DIID_IClientControl_Events, 0x00000002, Notification)
END_SINK_MAP()

// Handler prototypes:
// LRESULT MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam,
BOOL& bHandled);
// LRESULT CommandHandler(WORD wNotifyCode, WORD wID, HWND hWndCtl,
BOOL& bHandled);
// LRESULT NotifyHandler(int idCtrl, LPNMHDR pnmh, BOOL& bHandled);

LRESULT OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL&
bHandled);
LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);

protected:
// Events
VOID __stdcall StatusChanged()
{

}

VOID __stdcall Notification()
{
//OnClientControlNotification();
}
private:
CComPtr<ClientControl::IClientControl> m_pClientControl;
CAxWindow m_VoipWnd;
AddThis Social Bookmark Button