C3374: impossibile prendere l'indirizzo di 'funzione' a meno che non si crei un'istanza delegata

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

  •  03-07-2019
  •  | 
  •  

Domanda

Ho difficoltà a utilizzare una funzione di registrazione della libreria di terze parti per registrare un callback. Sto scrivendo in CLI C ++ e accedendo a una libreria scritta in C o C ++.

Cosa significa l'errore del compilatore sopra indicato?

questa è la funzione di registrazione definita dal venditore:

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

questo è il callback come definito dal fornitore:

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

La mia funzione di richiamata:

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

La mia chiamata (che non riesce):

MyCo_Device_Register_CallbackFunc((LPVOID) Device::CallBackFunc, nullptr, 0xFFFF);
È stato utile?

Soluzione

Se dovessi scommettere un'ipotesi, stai provando a prendere l'indirizzo di una funzione GESTITA e passarlo come puntatore a funzione NATIVA. Non funzionerà affatto. Scrivi un bridge nativo (più difficile e probabilmente nessun vantaggio) oppure (e questo è l'approccio più semplice), crea un delegato e usa Marshal.GetFunctionPointerForDelegate . Non dimenticare che il delegato deve rimanere in vita per la durata che il codice nativo prevede di richiamare, quindi è molto probabile che sia necessario memorizzarlo da qualche parte.

Oh, e tutte le funzioni all'interno di una classe ref o di una classe di valore sono funzioni gestite, nel caso non fosse chiaro.

[MODIFICA] Risposta in espansione per coprire le domande nei commenti. Il primo passo è creare un delegato corrispondente. Per la funzione che hai fornito, sarà simile a questo:

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

Quindi, dovrai crearne uno:

CallbackFuncDelegate del = gcnew CallbackFuncDelegate(CallbackFunc);

E come notato in precedenza, dovresti archiviarlo nella tua classe come membro per assicurarti che non svanisca. Infine, è necessario ottenere il puntatore alla funzione e passarlo:

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

Penso che copra tutto. Tutto ciò che serve è usare il namespace System; e dovresti stare bene.

Altri suggerimenti

la funzione di callback è un membro - puntatore a membri e puntatori a funzioni sono cose diverse.

Anche nella soluzione di Promit:

CallbackFuncDelegate(CallbackFunc)

CallbackFunc non dovrebbe essere un membro di classe

Puoi scrivere semplicemente

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

e quindi utilizzare

Device::CallBackFunc
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top