C++/CLI: Generar eventos desde C++ y capturarlos en código manejado, parte II

En la entrada anterior, vimos como generar un evento desde una clase C++ nativa que tiene un wrapper C++/CLI como interfaz hacia .NET en el caso general en que deseamos pasar información extra en el evento, y dicha info no es de un tipo primitivo (o sea, un tipo que no conocen tanto C++ como .NET). Si sólo queremos pasar un float, un int, o cualquier tipo que conozcan tanto C++ como .NET, el método que vimos antes se simplifica un poco.

  1. En la clase nativa, definimos, por comodidad, un tipo puntero a función:
    typedef <retorno> ( __stdcall * PFOnEventoCallback )( <parametros> );
  2. En la misma clase, declaramos un atributo del tipo definido en 1):
    PFOnEventoCallback m_FireEvento;
  3. Dentro de la clase nativa, donde querramos disparar el evento:
    m_FireEvento( <parametros> );
    (Es buena idea inicializar m_FireEvento en NULL y validar que sea distinto de NULL antes de hacer el fire)
  4. Ahora debemos exponer un setter para este atributo, de este estilo:
    void CClaseNativa::registerOnEventoCallback( PFOnEventoCallback newVal ){
       m_FireEvento = newVal;
    }
  5. En la clase C++/CLI que funciona como wrapper de la nativa, definimos un delegate análogo al puntero a función nativo y un atributo de ese tipo:
    delegate <retorno> DCallback( <parametros> );
    // ...junto a los demas atributos
    DCallback ^ m_hDCallback;
  6. Publicamos el evento:
    event DCallback ^ OnEvento{
       void add( DCallback ^p ){
          m_hDCallback += p;
          m_pNativeInstance->registerCallback( PFOnEventoCallback(
          	Marshal::GetFunctionPointerForDelegate( p ).ToPointer() )
          );
       }
    
       void remove( DCallback ^p ){
          m_hDCallback -= p;                 
          m_pNativeInstance->registerCallback( NULL );
       }
    }
  7. Finalmente, el evento publicado en CLI puede ser capturado en .NET. Por ejemplo, en VB.NET:
    AddHandler ClaseCLI.OnEvento, AddressOf UnSubConIgualEncabezadoQueDCallback
    'Al terminar de usar'
    RemoveHandler ClaseCLI.OnEvento, AddressOf UnSubConIgualEncabezadoQueDCallback

Es un poco menos truculento que el caso general, pero estoy seguro de que la gente de Java me tiraría un ladrillo por la cabeza...

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