en mi próximo proyecto Quiero implementar una GUI para el código ya existente en C++. Mi plan es envolver la parte de C++ en una DLL e implementar la GUI en C#. Mi problema es que no sé cómo implementar una devolución de llamada desde la DLL no administrada al código C# administrado. Ya he hecho algo de desarrollo en C#, pero la interfaz entre el código administrado y no administrado es nueva para mí. ¿Alguien puede darme algunos consejos o consejos de lectura o un simple ejemplo para empezar? Desafortunadamente no pude encontrar nada útil.¿Cómo implementar la interfaz de devolución de llamada desde la DLL no administrada a la aplicación .net?
Respuesta
No necesita usar Marshal.GetFunctionPointerForDelegate(), el Marshalter P/Invoke lo hace automáticamente. Deberá declarar un delegado en el lado C# cuya firma sea compatible con la declaración del puntero a la función en el lado C++. Por ejemplo:
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
class UnManagedInterop {
private delegate int Callback(string text);
private Callback mInstance; // Ensure it doesn't get garbage collected
public UnManagedInterop() {
mInstance = new Callback(Handler);
SetCallback(mInstance);
}
public void Test() {
TestCallback();
}
private int Handler(string text) {
// Do something...
Console.WriteLine(text);
return 42;
}
[DllImport("cpptemp1.dll")]
private static extern void SetCallback(Callback fn);
[DllImport("cpptemp1.dll")]
private static extern void TestCallback();
}
Y el código correspondiente C++ utilizado para crear el archivo DLL no administrado:
#include "stdafx.h"
typedef int (__stdcall * Callback)(const char* text);
Callback Handler = 0;
extern "C" __declspec(dllexport)
void __stdcall SetCallback(Callback handler) {
Handler = handler;
}
extern "C" __declspec(dllexport)
void __stdcall TestCallback() {
int retval = Handler("hello world");
}
Eso es suficiente para empezar con él. Hay un millón de detalles que pueden meterlo en problemas, es probable que se encuentre con algunos de ellos. La forma mucho más productiva de obtener este tipo de código es escribir un contenedor en el lenguaje C++/CLI. Eso también le permite ajustar una clase de C++, algo que no puede hacer con P/Invoke. Un tutorial decente es available here.
Echa un vistazo a esto, Marshal.GetDelegateForFunctionPointer?
Consulte Marshal.GetFunctionPointerForDelegate, que le proporcionará un puntero a la función para llamar al código administrado (es decir, código C#) desde un código no administrado.
P/Invoke puede manejar la clasificación de un delegado administrado a un puntero de función. Entonces, si expone las API que registran una función de devolución de llamada desde su DLL y en C#, pase un delegado a esa función.
Hay un ejemplo en MSDN de hacer esto con la función EnumWindows. En ese artículo, tener cuidado de prestar atención a la línea en el punto 4 que dice:
Si, sin embargo, la función de devolución de llamada puede invocarse después se devuelve la llamada, el persona que llama administrado debe tomar medidas para garantizar que el delegado permanece sin recoger hasta que finaliza la función de devolución de llamada . Para obtener información detallada sobre sobre la prevención de la recolección de basura , consulte Interop Marshaling con Platform Invoke.
Lo que está diciendo es que debe asegurarse de que su delegado no sea basura hasta después de que el código administrado termine de llamarlo manteniendo una referencia en el código o fijándolo.
+1 para crítico: el uso de P/Invoke solo garantiza la validez del puntero durante la llamada; si lo está almacenando en la memoria caché, necesita fijarlo (no se puede usar para esconder una referencia) , soy sospechoso, pero eso no significa mucho :-) –
- 1. Devolución de llamada desde Delphi dll a la aplicación C#
- 2. Anular la llamada a DLL no administrado
- 3. Implementar la función de devolución de llamada en JNI usando la interfaz
- 4. Cómo implementar la devolución de llamada user_loader en Flask-Login
- 5. Rendimiento de la Llamada .dll no administrado desde C#
- 6. .NET - Copiar de matriz no administrada a matriz no administrada
- 7. Java utilizando la interfaz como una devolución de llamada
- 8. ¿Cómo puedo implementar una DLL no administrada con una aplicación WPF de hacer clic una vez?
- 9. Envoltura administrada con interfaz no administrada
- 10. Devolución de llamada no administrada que hace que la pila se desborde
- 11. Implicaciones de la excepción de lanzamiento en delegado de devolución de llamada no administrada
- 12. ¿Cómo navegar a implementar clase desde la interfaz en Eclipse?
- 13. ¿Cómo obtener la lista de funciones dentro de una DLL (administrada y no administrada)?
- 14. El atributo DllImport siempre carga la DLL no administrada
- 15. Cómo encontrar una lista de todas las DLL no administradas loadad mediante mi aplicación .net administrada
- 16. Sobrecarga de la llamada a la función DLL
- 17. ¿Cómo accedo a la solicitud desde la devolución de llamada de señal request_finished?
- 18. Knockout.js ViewModel cambiar la devolución de llamada?
- 19. ¿cómo puedo activar la devolución de llamada de error ajax en la devolución de llamada exitosa?
- 20. devolución de llamada de animación jquery - cómo pasar parámetros a la devolución de llamada
- 21. jQuery JSONP no llama a la devolución de llamada
- 22. Implementando la devolución de llamada del servicio a la actividad
- 23. Cómo usar JNA en .dll y .so con la misma firma de devolución de llamada
- 24. ¿Cómo implementar la interfaz de IComparable?
- 25. ¿Cómo se define la devolución de llamada before_symlink usando el libro de recetas de la aplicación?
- 26. ¿Cómo implementar el mecanismo de devolución de llamada en Rserve?
- 27. FB.getLoginStatus no dispara la función de devolución de llamada
- 28. ¿La llamada a setOnClickListener desde múltiples clases resulta en una sola devolución de llamada?
- 29. Agregue parámetros adicionales a la función de devolución de llamada
- 30. contestar la llamada entrante desde mi aplicación
Gracias nobugz, lo intentaré pronto. Y espero que no me meta en demasiados problemas ;-) – chrmue
me funciona a la perfección, ¡gracias de nuevo! – chrmue