C++/CLI: Trigger Events from native code and handle them in Managed Code, part II

In the previous post, we saw how to trigger an event from a C++ native class which has a C++/CLI wrapper as an interface to .NET. We dealt with the general case in which we wish to pass non trivial information (a class or a struct) along with the event. Today we'll see the more simple case in which we just need to pass a float or some other basic CLR type. As expected, things are quite simpler.

  1. In the native class, just for convenience, define a pointer to function type. Both returnType and parameters should be basic CLR types.
    typedef <returnType> ( __stdcall * PFOnEventCallback )( <parameters> );
  2. In the same class, declare a field of that type:
    PFOnEventCallback m_fireEvent;
  3. Still in the native class, go to where you wish to trigger the event:
    if (m_fireEvent)
       m_fireEvent( <parameters> );
    (It's good practice to initialize m_fireEvent to 0 or NULL, your choice)
  4. Define a registration method:
    void CNativeClass::registerOnEventCallback( PFOnEventCallback newVal ){
       m_fireEvent = newVal;
    }
  5. In the C++/CLI wrapper, define a delegate analogous to the native pointer to function. They should have the same returnType and parameters; since they are basic types, no explicit marshalling is needed.
    delegate <returnType> DCallback( <parameters> );
    // ...Alongside the other fields
    DCallback ^ m_hDCallback;
  6. Declare the managed event:
    event DCallback ^ Event{
       void add( DCallback ^p ){
          m_hDCallback += p;
          m_pNativeInstance->registerCallback(
             PFOnEventCallback(
                Marshal::GetFunctionPointerForDelegate( p ).ToPointer()
             )
          );
       }
    
       void remove( DCallback ^p ){
          m_hDCallback -= p;                 
          m_pNativeInstance->registerCallback( 0 );
       }
    }
  7. Finally, subscribe to the managed event from pure managed code. For example, in VB.NET:
    AddHandler CLIWrapper.Event, AddressOf SomeSubWithTheSameSignatureAsDCallback
    'When you are done or the object is disposed'
    RemoveHandler CLIWrapper.OnEvent, AddressOf SomeSubWithTheSameSignatureAsDCallback

It's a bit less convoluted than the general case, but I'm sure Java people would still punch me in the gonads. (No offense intended, on the contrary, I'd rather work in Java)

Comments

Popular posts from this blog

VB.NET: Raise base class events from a derived class

Apache Kafka - I - High level architecture and concepts

Upgrading Lodash from 3.x to 4.x