C3374: não pode tomar o endereço de 'função', a menos que a criação de instância de delegado
Pergunta
Estou tendo dificuldade em usar uma função de registro de biblioteca thirdparty para registrar um callback. Estou escrevendo em C ++ CLI, e acessar uma biblioteca escrita em C ou C ++.
O que a média erro do compilador acima?
Esta é a função de registro conforme definido pelo fornecedor:
MYCO int WINAPI MyCo_Device_Register_CallbackFunc(LPVOID func, LPVOID lpParam, DWORD mask);
Este é o retorno de chamada, conforme definido pelo fornecedor:
typedef void (CALLBACK* MyCo_Device_CallbackProc)(DWORD ddStatus, LPVOID lpParam);
A minha função de retorno:
public ref class Device
{
void CallBackFunc(DWORD ddStatus, LPVOID lpParam) {};
}
Meu chamado (que não):
MyCo_Device_Register_CallbackFunc((LPVOID) Device::CallBackFunc, nullptr, 0xFFFF);
Solução
Se eu tivesse que apostar um palpite, você está tentando tomar o endereço de uma função gerenciada e passá-lo como um ponteiro de função nativa. Isso não vai funcionar em tudo. Ou escrever uma ponte nativa (mais difícil e provavelmente nenhuma vantagem), ou (e esta é a abordagem mais fácil), crie um delegado e uso Marshal.GetFunctionPointerForDelegate . Não se esqueça que o delegado tem de permanecer vivo para a duração que os espera código nativo para chamar de volta, então você provavelmente necessidade de armazená-lo em algum lugar.
funções Oh, e todas as funções dentro de uma classe ref ou classe de valor são geridos, no caso de que não estava claro.
[EDIT] Expansão resposta às perguntas de cobertura nos comentários. O primeiro passo é criar um delegado correspondente. Para a função que você forneceu, ele vai ficar assim:
public delegate void CallbackFuncDelegate(DWORD ddStatus, LPVOID lpParam);
Em seguida, você precisa criar um:
CallbackFuncDelegate del = gcnew CallbackFuncDelegate(CallbackFunc);
E, como observado anteriormente, você deve armazenar que em sua classe como um membro, a fim de se certificar de que não desaparece. Por último, você precisa para obter o ponteiro de função e passá-lo para baixo:
MyCo_Device_Register_CallbackFunc((MyCo_Device_CallbackProc) Marshal::GetFunctionPointerForDelegate(del).ToPointer(), 0, 0);
Eu penso que cobre tudo. Tudo que você precisa é using namespace System; e você deve ser fino.
Outras dicas
seu func callback é membro -. Ponteiro para membros e ponteiros para funções são coisas diferentes
Mesmo em solução de Promit:
CallbackFuncDelegate(CallbackFunc)
CallbackFunc não deve ser membro da classe
Você pode escrever simplesmente
public ref class Device
{
static void CallBackFunc(DWORD ddStatus, LPVOID lpParam) {};
}
e, em seguida, usar
Device::CallBackFunc