Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible for native class to consume .NET event?

Tags:

c#

.net

c++-cli

Any idea how to initialize .NET delegate that points to method from 'mixed' class instance?

I have 'mixed' C++ class like this:

class CppMixClass
{
public:
    CppMixClass(void){
        dotNETclass->StateChanged += gcnew DotNetClass::ServiceStateEventHandler(&UpdateHealthState);
    }
   ~CppMixClass(void);
   void UpdateState(System::Object^ sender, DotNetClass::StateEventArgs^ e){
       //doSmth
   }
}

DotNetClass is implemented in C#, and Method declaration is OK with delegate. This line generates error:

dotNETclass->StateChanged += gcnew DotNetClass::ServiceStateEventHandler(&UpdateHealthState);
error C2276: '&' : illegal operation on bound member function expression

Anyone have a clue about a problem? Maybe coz CppMixClass class is not a pure .NET (ref) class?

I got this to work when UpdateHealthState is static method, but I need pointer to instance method.

I tried smth like:

dotNETclass->StateChanged += gcnew DotNetClass::ServiceStateEventHandler(this, &UpdateHealthState);

But this obviously doesn't work coz this is not pointer (handle) to .NET (ref) class, (System::Object).

ServiceStateEventHandler is defined in C# as:

public delegate void ServiceStateEventHandler(object sender, ServiceStateEventArgs e);

Thanx for reading this :)

like image 670
Jox Avatar asked Mar 01 '23 02:03

Jox


2 Answers

I just found answer to this(of course by Nishant Sivakumar, man seems to have answers to all my C++/CLI interop related problems):

http://www.codeproject.com/KB/mcpp/CppCliSupportLib.aspx?display=Print

Answer is located in "msclr/event.h" header, where macros for delegates in native classes are defined.

Nish's code is following:

class Demo5
{
msclr::auto_gcroot<FileSystemWatcher^> m_fsw;
public:
// Step (1)
// Declare the delegate map where you map
// native method to specific event handlers

BEGIN_DELEGATE_MAP(Demo5)
    EVENT_DELEGATE_ENTRY(OnRenamed, Object^, RenamedEventArgs^)
END_DELEGATE_MAP()

Demo5()
{
    m_fsw = gcnew  FileSystemWatcher("d:\\tmp");
    // Step (2)
    // Setup event handlers using MAKE_DELEGATE
    m_fsw->Renamed += MAKE_DELEGATE(RenamedEventHandler, OnRenamed);
    m_fsw->EnableRaisingEvents = true;
}
// Step (3)
// Implement the event handler method

void OnRenamed(Object^, RenamedEventArgs^ e)
{
    Console::WriteLine("{0} -> {1}",e->OldName, e->Name);
}
};
like image 120
Jox Avatar answered Mar 12 '23 16:03

Jox


Only .NET types can use events. I suggest creating a new managed class that handles the event, and compose that class within CppMixClass, and pass it a pointer to CppMixClass during construction. Your managed event handling class can then call a function on CppMixClass when it handles an event.

like image 20
Rob Avatar answered Mar 12 '23 14:03

Rob