C3374: no se puede tomar la dirección de 'function' a menos que se cree una instancia delegada

StackOverflow https://stackoverflow.com/questions/822582

  •  03-07-2019
  •  | 
  •  

Pregunta

Tengo dificultades para utilizar una función de registro de biblioteca de terceros para registrar una devolución de llamada. Estoy escribiendo en C ++ CLI y accediendo a una biblioteca escrita en C o C ++.

¿Qué significa el error del compilador anterior?

esta es la función de registro definida por el proveedor:

MYCO int WINAPI MyCo_Device_Register_CallbackFunc(LPVOID func, LPVOID lpParam, DWORD mask);

esta es la devolución de llamada definida por el proveedor:

typedef void (CALLBACK* MyCo_Device_CallbackProc)(DWORD ddStatus, LPVOID lpParam);

Mi función de devolución de llamada:

public ref class Device 
{
    void CallBackFunc(DWORD ddStatus, LPVOID lpParam) {};
}

Mi llamada (que falla):

MyCo_Device_Register_CallbackFunc((LPVOID) Device::CallBackFunc, nullptr, 0xFFFF);
¿Fue útil?

Solución

Si tuviera que apostar una conjetura, está intentando tomar la dirección de una función ADMINISTRADA y pasarla como un indicador de función NATIVO. Eso no funcionará en absoluto. Escriba un puente nativo (más difícil y probablemente sin ventaja) o (y este es el enfoque más fácil), cree un delegado y use Marshal.GetFunctionPointerForDelegate . No olvide que el delegado tiene que permanecer vivo durante el tiempo que el código nativo espera volver a llamar, por lo que lo más probable es que deba almacenarlo en algún lugar.

Ah, y todas las funciones dentro de una clase de referencia o clase de valor son funciones administradas, en caso de que eso no esté claro.

[EDITAR] Ampliando respuesta para cubrir preguntas en comentarios. El primer paso es crear un delegado correspondiente. Para la función que proporcionó, se verá así:

public delegate void CallbackFuncDelegate(DWORD ddStatus, LPVOID lpParam);

Luego, deberás crear una:

CallbackFuncDelegate del = gcnew CallbackFuncDelegate(CallbackFunc);

Y como se mencionó anteriormente, debes guardar eso EN tu clase como miembro para asegurarte de que no desaparezca. Por último, debe obtener el puntero de la función y pasarlo:

MyCo_Device_Register_CallbackFunc((MyCo_Device_CallbackProc) Marshal::GetFunctionPointerForDelegate(del).ToPointer(), 0, 0);

Creo que eso cubre todo. Todo lo que necesitas es usar el sistema de espacio de nombres; y deberías estar bien.

Otros consejos

su función de devolución de llamada es un miembro: el puntero a los miembros y los punteros a las funciones son cosas diferentes.

Incluso en la solución de Promit:

CallbackFuncDelegate(CallbackFunc)

CallbackFunc no debe ser miembro de la clase

Puedes escribir simplemente

public ref class Device 
{
    static void CallBackFunc(DWORD ddStatus, LPVOID lpParam) {};
}

y luego use

Device::CallBackFunc
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top