2010-05-27 15 views
6

Estoy realmente confundido por la multitud de información errónea sobre la interoperabilidad nativa/administrada.Llamar a una devolución de llamada nativa desde el código .NET administrado (al cargar el código administrado usando COM)

Tengo un C++ exe normal que NO está construido con CLR (no es administrado por C++ ni por C++/CLI y nunca lo será). Este C++ exe está "a cargo", no hay un contenedor administrado para él.

Me gustaría acceder a algún código que tengo en un ensamblado C# de mi C++ exe. Puedo acceder al ensamblado C# desde mi código C++ usando COM. Sin embargo, cuando mi código C# detecta un evento, me gustaría llamar a mi código C++. El puntero de la función C++ para devolver la llamada se proporcionará en tiempo de ejecución. Tenga en cuenta que el puntero de la función C++ se corresponde con una función que se encuentra en el entorno de ejecución del exe. Puede usar miembros estáticos desde allí. No quiero que el código administrado intente cargar una DLL para llamar a una función (no hay una DLL).

¿Cómo paso este puntero de función C++ a mi código C# a través de COM/.NET y hago que mi código C# lo llame con éxito?

Gracias!

Respuesta

6

Es probable que desee utilizar Marshal.GetDelegateForFunctionPointer:

  1. Crear un tipo de delegado que coincide con la firma de la función nativa, teniendo en cuenta la manera correcta para reunir y utilizar tipos MarshalAs, según sea necesario
  2. Comunicar el puntero de la función nativa desde su código nativo a su código C# como sea que pueda (en su caso, parece que puede usar su conexión COM -> C#)
  3. Use Marshal.GetDelegateForFunctionPointer para convertir el puntero en un delegado de C#callable
  4. Invocar el delegado con sus parámetros

Junfeng Zhang tiene un ejemplo de hacer esto here.

Nota las restricciones mencionadas en MSDN:

El método GetDelegateForFunctionPointer tiene las siguientes restricciones:

  • genéricos no son compatibles con la interoperabilidad escenarios.
  • No puede pasar una función no válida puntero a este método.
  • Puede utilizar este método solo para punteros de función no administrados puros.
  • No puede utilizar este método con los punteros de función obtenidos a través de C++ o del método GetFunctionPointer.
  • No puede usar este método para crear un delegado desde un puntero de función a otro delegado administrado.

La parte acerca de C++ es probable refiriendo a los punteros de función para los métodos de la clase. Esto todavía debería funcionar para funciones globales.

+0

En el paso 2, ¿el puntero de función llegará inicialmente en C# -y como IntPtr? – evilfred

+1

Para obtener el puntero de C/C++ a C#, se calculará. Sí, los punteros C/C++ se representan como C# 'IntPtr' cuyo tamaño es específico de la plataforma. –

+0

Probablemente estoy haciendo algo tonto. El compilador de C++ se queja de que no puede convertir mi parámetro de voic (__ cdecl *) (UINT) a long (el método toma un IntPtr en C#). Además, el ejemplo de Zhang implica un puntero de función de C++ recuperado en C# no recuperado de C++ ... – evilfred

4

El enfoque COM estándar es suscribirse a un evento que se genera por el servidor COM. El uso puede usar la palabra clave del evento en C#, CLR interop implementa automáticamente el pegamento COM que se necesita. Use la interfaz IConnectionPoint en su código C++. Antecedentes is here.

Cuestiones relacionadas