2010-12-03 24 views
2

En tant que développeur C#, je pense que beaucoup d'entre nous ont l'expérience d'appeler du code managé à partir de code managé.Que devrait savoir un développeur sur l'interopérabilité avec le code managé

Quel est le problème le plus difficile que vous avez jamais rencontré en matière d'interopérabilité entre le code managé et le code non géré? (Vous devez donner des exemples de code tels que la signature de fonction C++ et les wrappers C#)

Comment déboguer l'erreur d'exécution puisque aucune information de débogage de haut niveau fournie par Visual Studio lors de l'appel?

Répondre

4

En général, trouver une référence faisant autorité pour les déclarations P/Invoke est difficile si vous ne savez pas assez sur C pour obtenir la bonne déclaration. Il y a beaucoup de mauvaises déclarations sur Internet. Les pièges typiques sont les déclarations VB6, il y a un lot là-bas, où les arguments qui sont vraiment int sont déclarés comme Long. Long est le type intégral 32 bits dans VB6, Integer est 16 bits pour des raisons historiques.

Une autre erreur répandue consiste à utiliser int où IntPtr est requis. Ces déclarations fonctionnent correctement en mode 32 bits mais se comportent mal en mode 64 bits. Les fonctions prenant 4 arguments ou moins sont particulièrement gênantes, le mauvais type d'argument ne génère pas l'avertissement MDA PInvokeStackImbalance car les 4 premiers arguments de la fonction sont passés dans les registres de la CPU. Ce bug a tendance à mordre longtemps après que l'auteur a déclaré que le travail a été fait, assez dur pour y revenir et diagnostiquer le problème.

Le problème suivant est l'ennui de la déclaration et de la maintenance des déclarations P/Invoke ou des encapsuleurs C++/CLI. Lorsque l'API non gérée est grande, vous finirez par écrire beaucoup d'entre eux. Chacun d'eux est prêt à vous donner une erreur difficile à diagnostiquer lorsque vous l'obtenez subtilement faux.

L'interopérabilité réelle est avec les serveurs COM dotés d'interfaces IUnknown. De tels serveurs n'ont pas de bibliothèque de types, donc il n'y a aucune opportunité d'utiliser Tlbimp.exe pour générer automatiquement la bibliothèque interop. Vous devez re-déclarer les interfaces dans votre code C# et assurez-vous d'avoir [Guid] et les déclarations de méthode correctes. Le manque de prise en charge de l'héritage multiple nécessite de sauter par des cerceaux supplémentaires lorsque l'interface hérite d'une interface IUnknown intermédiaire. Le problème que this author appelle incorrectement la «taxe d'héritage».

Ces types de serveurs sont beaucoup plus courants que d'habitude. À peu près tout ce que vous voulez faire avec le shell (explorer.exe) est IUnknown basé par exemple. Il en va de même pour les extensions Vista et Win7, habilement enveloppées par le Windows Code Code Pack btw.

Et oui, la gestion des erreurs. Trop de code non géré là-bas qui ne renvoient rien d'autre qu'un code d'erreur hostile comme E_FAIL ou E_UNEXPECTED. Et n'implémente pas IErrorInfo donc tout ce que vous avez est un message générique inutile à regarder. Ou API qui retournent BOOL pour indiquer un échec, invitant un programmeur à simplement ignorer la valeur de retour. Et AccessViolation ou Fatal Engine Execution Error, le code non géré exploser dans votre visage sans laisser de fil d'Ariane pour trouver ce qui s'est mal passé. Ce n'est pas particulier à l'interopérabilité C#, un tel code est difficile à utiliser pour n'importe qui.

Autre que cela, il est généralement assez simple de le faire fonctionner. Le marshaller P/Invoke et le support COM Interop dans .NET sont vraiment excellents et significativement meilleurs que ce qui est disponible dans d'autres VM.

0

Cadres de comptage de référence: alors que le CLR peut ramasser toute la mémoire qu'il n'utilise plus, il connaît le zip de la mémoire dans vos bibliothèques non gérées. Par conséquent, vous devez libérer manuellement les ressources obtenues à partir de sources non gérées.