2009-06-26 8 views
1

Petit peu d'une leçon d'histoire ici. Je travaille sur une application C++/MFC existante et j'essaie de démarrer une modernisation incrémentielle en poussant des composants écrits en C# (WinForms et plus tard WPF).Code de rappel non géré de C géré

Je bloque en utilisant .Net/1.1 et VS/2003 pour de nombreuses raisons qui sont impossibles à résoudre dans un proche avenir.

Actuellement, comme une preuve de concept, quelque chose comme cela fonctionne:

#pragma push_macro("new") 
#undef new 

WinFormA::Form1* myform; 
myform = __gc new WinFormA::Form1(); 
myform->ShowDialog(); 

#pragma pop_macro("new") 

Le problème que je vais avoir est - je besoin du non géré le code C++/MFC pour passer un pointeur de rappel dans la gestion C# WinForm code afin que je puisse capturer les interactions des utilisateurs et les faire traiter par l'application.

J'ai regardé quelques articles tels que this MSDN article mais cela ne fonctionne pas dans VS/2003 (le compilateur n'aime pas la syntaxe de délégué).

Y a-t-il d'autres options? Je ne pense pas pouvoir utiliser DLLImport car j'ai besoin d'interagir avec l'instance d'application spécifique et non avec une API plate.

Merci!

Répondre

0

je l'ai déjà oublié .NET 1. *, mais:

Définir les interfaces nécessaires et enregistrer votre composants .NET comme des objets COM. Les utilitaires .NET fournissent généralement un code de marshaling raisonnablement bon.

Si possible, accédez-y en tant qu'objets COM à partir de l'application C++ sans aucun C++ managé. (Utilisez des pointeurs d'interface au lieu de fonctions pour les rappels).

Si COM n'est pas une option, utilisez .NET Reflector pour voir ce qui se passe à l'intérieur des assemblages interop générés automatiquement - ceci pourrait donner un aperçu sur la façon de faire la même chose manuellement.

0

Je ne l'ai jamais essayé moi-même, mais avez-vous vérifié la structure RuntimeMethodHandle qui existe certainement dans .net1?

SomeDelegate Handler = new SomeDelegate(SomeMethod); 
IntPtr HandlerPtr = Handler.Method.MethodHandle.GetFunctionPointer(); 

Et certains copier-coller de la description de MSDN .NET2 maréchal :: GetDelegateForFunctionPointer Méthode:

Dans les versions 1.0 et 1.1 du .NET Framework, il était possible de passer un délégué représentant une méthode gérée en code non managé en tant que pointeur de fonction, permettant au code non managé d'appeler la méthode gérée via le pointeur de fonction. Il était également possible pour le code non managé de renvoyer ce pointeur de fonction au code managé et le pointeur a été résolu correctement à la méthode managée sous-jacente.

1

Si les autres réponses ne fonctionnent pas, vous pouvez toujours écrire un wrapper C pour aplatir les classes.Par exemple, si la classe C++ est:

class TheClass { 
    public: 
    TheClass(int Param); 
    ~TheClass(); 

    bool SomeFunction(int Param1,int Param2); 
}; 

Je vais écrire un wrapper:

extern "C" void *TheClass_Create(int Param) { 
    return (void*) new TheClass(Param); 
} 

extern "C" void TheClass_Destroy(void *This) { 
    delete (TheClass*) This; 
} 

extern "C" bool TheClass_SomeFunction(void *This,int Param1,int Param2) { 
    return ((TheClass*) This)->SomeFunction(Param1,Param2); 
} 

Parce que l'emballage est C droite, vous pouvez P/Invoke en C# au contenu de votre coeur (la void * Ce devrait devenir un IntPtr pour assurer la compatibilité si vous passez en 64 bits). Parfois, si je suis vraiment ambitieux, je vais écrire un wrapper C# autour du P/Invoke pour "re-classifier" la chose.

Questions connexes