c# - usar - ¿Cómo implementar la interfaz de devolución de llamada de DLL no administrada a la aplicación.net?
dll visual studio (4)
Consulte Marshal.GetFunctionPointerForDelegate , que le dará un indicador de función para llamar administrado (es decir, código C #) desde código no administrado.
en mi próximo proyecto quiero implementar una GUI para código ya existente en C ++. Mi plan es envolver la parte C ++ en una DLL e implementar la GUI en C #. Mi problema es que no sé cómo implementar una devolución de llamada de la DLL no administrada en el código C # administrado. Ya he hecho algo de desarrollo en C #, pero la interfaz entre el código administrado y el no administrado es nueva para mí. ¿Alguien puede darme algunos consejos o consejos de lectura o un ejemplo simple para comenzar? Desafortunadamente no pude encontrar nada útil.
Echa un vistazo a esto, Marshal.GetDelegateForFunctionPointer ?
No es necesario usar Marshal.GetFunctionPointerForDelegate (), el encargado de invocar P / Invoke lo hace automáticamente. Deberá declarar un delegado en el lado C # cuya firma es compatible con la declaración de puntero de 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 de C ++ correspondiente utilizado para crear la DLL no administrada:
#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 que comiences con eso. Hay un millón de detalles que pueden meterte en problemas, estás obligado a encontrarte con algunos de ellos. La forma mucho más productiva de poner en marcha este tipo de código es escribir un contenedor en el lenguaje C ++ / CLI. Eso también le permite envolver una clase de C ++, algo que no puede hacer con P / Invoke. Un tutorial decente está disponible aquí.
P / Invoke puede manejar el cálculo de referencias 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 de 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, preste atención a la línea del punto 4 que dice:
Sin embargo, si la función de devolución de llamada se puede invocar después de que se devuelva la llamada, la persona que llama administrada debe tomar medidas para garantizar que el delegado permanezca sin cobrar hasta que finalice la función de devolución de llamada. Para obtener información detallada sobre la prevención de la recolección de basura, consulte Interop Marshaling with Platform Invoke.
Lo que está diciendo es que debe asegurarse de que su delegado no se recoja basura hasta después de que el código administrado haya terminado de llamarlo, ya sea manteniendo una referencia a él en su código, o fijándolo.