2009-05-04 9 views
3

J'ai de la difficulté à 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++.C3374: impossible de prendre l'adresse de 'fonction' à moins de créer une instance de délégué

Que signifie l'erreur de compilation ci-dessus?

c'est la fonction d'enregistrement telle que définie par le vendeur:

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

c'est la fonction de rappel tel que défini par le vendeur:

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); 
+0

double: http://stackoverflow.com/questions/822526/how-do-i-register-a-callback-in-ac-library-from-my-cli-wrapper – lothar

+0

cette question a été supprimée – MedicineMan

+0

J'ai développé ma réponse en bas. – Promit

Répondre

8

Si je devais faire une supposition, vous essayez de prendre l'adresse d'une fonction MANAGED et de la passer comme un pointeur de fonction NATIVE. Cela ne marchera pas du tout. Soit écrire un pont natif (plus difficile et probablement pas d'avantage), ou (et c'est l'approche la plus facile), créer un délégué et utiliser Marshal.GetFunctionPointerForDelegate. N'oubliez pas que le délégué doit rester en vie pendant la durée que le code natif s'attend à rappeler, vous devez donc probablement le stocker quelque part. Oh, et toutes les fonctions à l'intérieur d'une classe de référence ou d'une classe de valeur sont des fonctions gérées, au cas où ce n'était pas clair.

[EDIT] Extension de la réponse aux questions de couverture dans les commentaires. La première étape consiste à créer un délégué correspondant. Pour la fonction que vous avez fourni, il va ressembler à ceci:

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

Ensuite, vous devrez créer un:

CallbackFuncDelegate del = gcnew CallbackFuncDelegate(CallbackFunc); 

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

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

Je pense que cela couvre tout. Tout ce dont vous avez besoin est d'utiliser namespace System; et ça devrait aller. Votre fonction de callback est un membre - pointeur vers les membres et les pointeurs vers les fonctions sont des choses différentes.

+0

Je pense que vous avez frappé le clou sur la tête. Comment le code que vous suggérez ressemble-t-il, et ce dont j'ai besoin? – MedicineMan

+0

et comment puis-je m'assurer que je garde le délégué vivant pour qu'il ne soit pas collecté (gestion de la durée de vie) – MedicineMan

+0

J'ai apporté les modifications suivantes: 1.^manquant dans la création de délégué 2. & manquant quand gcnew-ing le délégué CallbackFuncDelegate^del = gcnew CallbackFuncDelegate (& H8Device :: BtnCallBackFunc); – MedicineMan

0

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 
+0

votre suggestion a résolu le problème de compilation, mais il semble étrange que j'ai maintenant une méthode statique qui n'a pas accès aux données privées (ne peut rien faire). Je me demande si cela va fonctionner – MedicineMan

+0

Tout d'abord - il a accès à des données privées ** statiques **. Deuxièmement - vous pouvez créer une sorte de singleton 8). Utilisez ce modèle directement - ou créez un délégué qui aura une fonction statique et un pointeur statique vers l'objet. Et juste pour clarifier au sujet de question pointeur à membre: vous pouvez lire ici une introduction http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=142 Pour rendre la longue histoire short - votre callback-func initial (non-statique) a besoin de ce pointeur - c'est pourquoi le pointeur-à-un membre est différent - vous pouvez l'utiliser seulement si vous avez un objet –

+0

Merci pour la suggestion. Changer ma classe pour être un singleton afin d'utiliser les rappels ne me semble pas tout à fait correct. – MedicineMan

Questions connexes