2010-05-27 6 views
6

Je suis vraiment confus par la multitude d'informations erronées sur l'interopérabilité native/gérée.Appel d'un rappel natif à partir du code .NET géré (lors du chargement du code managé à l'aide de COM)

J'ai un C++ exe régulier qui n'est pas construit en utilisant CLR stuff (ce n'est ni Managed C++ ni C++/CLI et ne le sera jamais). Ce C++ exe est "en charge", il n'y a pas de wrapper géré pour cela.

Je voudrais accéder à du code que j'ai dans un assembly C# de mon exe C++. Je peux accéder à l'assembly C# à partir de mon code C++ en utilisant COM. Cependant, lorsque mon code C# détecte un événement, je voudrais le rappeler dans mon code C++. Le pointeur de la fonction C++ à rappeler sera fourni lors de l'exécution. Notez que le pointeur de fonction C++ est une fonction trouvée dans l'environnement d'exécution de l'exe. Il peut utiliser des membres statiques à partir de là. Je ne veux pas que le code managé essaie de charger une DLL pour appeler une fonction (il n'y a pas de DLL). Comment puis-je transmettre ce pointeur de fonction C++ à mon code C# via COM/.NET et que mon code C# appelle avec succès?

Merci!

Répondre

6

Vous voudrez probablement utiliser Marshal.GetDelegateForFunctionPointer:

  1. Créer un type délégué qui correspond à la signature de la fonction native, en gardant à l'esprit la bonne façon de rassembler les types et l'utilisation MarshalAs comme nécessaire
  2. Communicate le pointeur de la fonction native de votre code natif à votre code C# cependant, vous pouvez (dans votre cas, il semble que vous pouvez utiliser votre COM -> C# connexion)
  3. utilisez Marshal.GetDelegateForFunctionPointer pour transformer le pointeur en C# délégué -callable
  4. Appelez le délégué avec vos paramètres

Junfeng Zhang a un exemple de cela here.

Notez les restrictions mentionnées sur MSDN:

La méthode GetDelegateForFunctionPointer a les restrictions suivantes:

  • Generics ne sont pas pris en charge dans les scénarios Interop .
  • Vous ne pouvez pas passer une fonction non valide pointeur à cette méthode.
  • Vous pouvez utiliser cette méthode uniquement pour les pointeurs de fonction non gérés purs.
  • Vous ne pouvez pas utiliser cette méthode avec les pointeurs de fonction obtenus via C++ ou à partir de la méthode GetFunctionPointer.
  • Vous ne pouvez pas utiliser cette méthode pour créer un délégué à partir d'un pointeur de fonction à un autre délégué géré.

La partie sur C++ est probablement référence à des pointeurs de fonction pour les méthodes de classe. Cela devrait toujours fonctionner pour les fonctions globales.

+0

A l'étape 2, le pointeur de fonction arrivera-t-il initialement dans C# -land en tant que IntPtr? – evilfred

+1

Pour obtenir le pointeur de C/C++ à C#, il sera marshalé. Oui, les pointeurs C/C++ sont représentés par un C# IntPtr dont la taille est spécifique à la plate-forme. –

+0

Je fais probablement quelque chose de stupide. Le compilateur C++ se plaint qu'il ne peut pas convertir mon paramètre de voic (__ cdecl *) (UINT) en long (la méthode prend un IntPtr en C#). En outre, l'exemple de Zhang implique un pointeur de fonction C++ récupéré en C# et non récupéré en C++ ... – evilfred

4

L'approche COM standard consiste à s'abonner à un événement déclenché par le serveur COM. L'utilisation peut utiliser le mot-clé d'événement en C#, l'interopérabilité CLR implémente automatiquement la colle COM requise. Utilisez l'interface IConnectionPoint dans votre code C++. Document d'information is here.

Questions connexes