C3374: impossible de prendre l'adresse de 'fonction' à moins de créer une instance de délégué

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

  •  03-07-2019
  •  | 
  •  

Question

Je ne parviens pas à utiliser une fonction d'enregistrement de bibliothèque tierce pour enregistrer un rappel. J'écris en C ++ CLI et j'accède à une bibliothèque écrite en C ou C ++.

Qu'est-ce que l'erreur de compilation ci-dessus signifie?

C’est la fonction d’enregistrement telle que définie par le fournisseur:

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

il s'agit du rappel tel que défini par le fournisseur:

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

Ma fonction de rappel:

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

Mon appel (qui échoue):

MyCo_Device_Register_CallbackFunc((LPVOID) Device::CallBackFunc, nullptr, 0xFFFF);
Était-ce utile?

La solution

Si je devais miser une conjecture, vous essayez de prendre l'adresse d'une fonction MANAGED et de la transmettre en tant que pointeur de fonction NATIVE. Cela ne fonctionnera pas du tout. Soit écrire un pont natif (plus difficile et probablement pas d’avantage), ou (c’est l’approche la plus simple), créer un délégué et utiliser Marshal.GetFunctionPointerForDelegate . N'oubliez pas que le délégué doit rester en vie aussi longtemps que le code natif s'attend à ce qu'il soit rappelé. Vous devez donc probablement le stocker quelque part.

Oh, et toutes les fonctions d'une classe de référence ou de classe de valeur sont des fonctions gérées, au cas où cela ne soit pas clair.

[EDIT] Extension de la réponse pour couvrir les questions dans les commentaires. La première étape consiste à créer un délégué correspondant. Pour la fonction que vous avez fournie, cela ressemblera à ceci:

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

Ensuite, vous devrez en créer un:

CallbackFuncDelegate del = gcnew CallbackFuncDelegate(CallbackFunc);

Et comme indiqué précédemment, vous devez stocker le résultat dans votre classe en tant que membre afin de vous assurer qu'il ne disparaît pas. Enfin, vous devez obtenir le pointeur de la fonction et le transmettre:

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

Je pense que ça couvre tout. Tout ce dont vous avez besoin est d'utiliser le système d'espace de noms; et ça devrait aller.

Autres conseils

votre fonction de rappel est un membre - les pointeurs sur les membres et les pointeurs sur les fonctions sont différentes.

Même dans la solution de Promit:

CallbackFuncDelegate(CallbackFunc)

CallbackFunc ne doit pas être membre de la classe

Vous pouvez écrire simplement

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

puis utilisez

Device::CallBackFunc
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top