Share via


Vue d’ensemble de l’interopérabilité entre le code managé et le code non managé

 

Sonja Keserovic, responsable de programme
David Mortenson, ingénieur en conception de logiciels en chef
Adam Nathan, ingénieur principal en conception de logiciels en test

Microsoft Corporation

Octobre 2003

S’applique à :
   Microsoft® .NET Framework
   COM Interop

Résumé: Cet article fournit des faits de base sur l’interopérabilité entre le code managé et le code non managé, ainsi que des instructions et des pratiques courantes pour l’accès et l’encapsulation d’API non managées à partir du code managé, et pour exposer les API managées aux appelants non managés. Les considérations relatives à la sécurité et à la fiabilité, les données de performances et les pratiques générales pour les processus de développement sont également mises en évidence. (14 pages imprimées)

Conditions préalables: Le public cible de ce document comprend des développeurs et des responsables qui doivent prendre des décisions générales sur l’emplacement d’utilisation du code managé. Pour ce faire, il est utile de comprendre comment fonctionne l’interaction entre le code managé et le code non managé, et comment les instructions actuelles s’appliquent à des scénarios spécifiques.

Contenu

Présentation de l’interopérabilité
Directives d’interopérabilité
Sécurité
Fiabilité
Performances
Annexe 1 : Dépassement de la limite d’interopérabilité
Annexe 2 : Ressources
Annexe 3 : Glossaire des termes

Présentation de l’interopérabilité

Le Common Language Runtime (CLR) favorise l’interaction du code managé avec les composants COM, les services COM+, l’API Win32® et d’autres types de code non managé. Les types de données, les mécanismes de gestion des erreurs, les règles de création et de destruction et les instructions de conception varient entre les modèles objet managés et non managés. Pour simplifier l’interopérabilité entre le code managé et le code non managé et faciliter le chemin de migration, la couche d’interopérabilité CLR masque les différences entre ces modèles objet des clients et des serveurs.

L’interopérabilité (« interopérabilité ») est bidirectionnelle, ce qui permet de :

  • Appeler des API non managées à partir de code managé

    Cela peut être effectué pour les API plates (exportations DLL statiques, telles que l’API Win32, qui est exposée à partir de DLL telles que kernel32.dll et user32.dll) et les API COM (modèles objet tels que ceux exposés par Microsoft® Word, Excel, Internet Explorer, ActiveX® Data Objects (ADO) et ainsi de suite).

  • Exposer des API managées à du code non managé

    Par exemple, la création d’un complément pour une application COM telle que le Lecteur Windows Media® ou l’incorporation d’un contrôle de Windows Forms managé dans un formulaire MFC.

Trois technologies complémentaires permettent ces interactions managées/non managées :

  • Platform Invoke (parfois appelé P/Invoke) permet d’appeler n’importe quelle fonction dans n’importe quel langage non managé tant que sa signature est redeclarée dans le code source managé. Ceci est similaire à la fonctionnalité fournie par l’instruction Declare dans Visual Basic® 6.0.
  • COM Interop permet d’appeler des composants COM dans n’importe quel langage managé d’une manière similaire à l’utilisation de composants managés normaux, et vice versa. COM Interop comprend les services principaux fournis par le CLR, ainsi que certains outils et API dans l’espace de noms System.Runtime.InteropServices .
  • L’interopérabilité C++ (parfois appelée It Just Works (IJW) est une fonctionnalité spécifique à C++, qui permet d’utiliser directement les API plates et les API COM, car elles ont toujours été utilisées. C’est plus puissant que COM Interop, mais il nécessite beaucoup plus de soin. Veillez à case activée les ressources C++ avant d’utiliser cette technologie.

Directives d’interopérabilité

Appel d’API non managées à partir de code managé

Il existe plusieurs types d’API non managées et plusieurs types de technologies d’interopérabilité disponibles pour les appeler. Des suggestions sur la façon et le moment d’utiliser ces technologies sont décrites dans cette section. Notez que ces suggestions sont très générales et ne couvrent pas tous les scénarios. Vous devez évaluer soigneusement vos scénarios et appliquer des pratiques de développement et/ou des solutions adaptées à votre scénario.

Appel d’API plates non managées

Il existe deux mécanismes pour appeler des API plates non managées à partir de code managé : via l’appel de plateforme (disponible dans tous les langages managés) ou l’interopérabilité C++ (disponible en C++).

Avant de décider d’appeler une API plate à l’aide de l’une de ces technologies d’interopérabilité, vous devez déterminer si des fonctionnalités équivalentes sont disponibles dans le .NET Framework. Dans la mesure du possible, il est recommandé d’utiliser la fonctionnalité .NET Framework au lieu d’appeler des API non managées.

Pour appeler seulement quelques méthodes non managées ou pour appeler des API plates simples, il est suggéré d’utiliser l’appel de plateforme au lieu de l’interopérabilité C++. L’écriture de déclarations d’appel de plateforme pour les API plates simples est simple. Le CLR prend en charge le chargement des DLL et le marshaling de tous les paramètres. Même le travail d’écriture de quelques déclarations d’appel de plateforme pour des API plates complexes est négligeable par rapport au coût de l’interopérabilité C++ et de l’introduction d’un tout nouveau module écrit en C++.

Pour encapsuler des API plates complexes non managées ou pour encapsuler des API plates non managées qui changent pendant le développement du code managé, il est suggéré d’utiliser l’interopérabilité C++ au lieu de l’appel de plateforme. La couche C++ peut être très fine et le reste du code managé peut être écrit dans n’importe quel autre langage managé de votre choix. L’utilisation de l’appel de plateforme dans ces scénarios nécessiterait beaucoup d’efforts pour déclarer à nouveau des parties complexes de l’API dans du code managé et les maintenir synchronisées avec les API non managées. L’utilisation de L’interopérabilité C++ résout ce problème en autorisant l’accès direct aux API non managées, ce qui ne nécessite aucune réécriture, mais simplement l’inclusion d’un fichier d’en-tête.

Appel des API COM

Il existe deux façons d’appeler des composants COM à partir de code managé : via l’interopérabilité COM (disponible dans tous les langages managés) ou l’interopérabilité C++ (disponible en C++).

Pour appeler des composants COM compatibles OLE Automation, il est suggéré d’utiliser l’interopérabilité COM. Le CLR s’occupe de l’activation des composants COM et du marshaling des paramètres.

Pour appeler des composants COM basés sur IDL (Interface Definition Language), il est suggéré d’utiliser l’interopérabilité C++. La couche C++ peut être très fine et le reste du code managé peut être écrit dans n’importe quel langage managé. COM Interop s’appuie sur les informations des bibliothèques de types pour effectuer des appels d’interopérabilité corrects, mais les bibliothèques de types ne contiennent généralement pas toutes les informations présentes dans les fichiers IDL. L’utilisation de l’interopérabilité C++ résout ce problème en autorisant l’accès direct à ces API COM.

Pour les entreprises qui possèdent des API COM qui ont déjà été livrées, il est important d’envisager d’expédier des assemblys PIA (Primary Interop Assemblys) pour ces API, ce qui les rend faciles à utiliser pour les clients managés.

Arbre de décision pour l’appel d’API non managées

Figure 1. Appel de l’arbre de décision des API non managées

Exposition d’API managées à du code non managé

Il existe deux façons main d’exposer une API managée à des appelants purement non managés : en tant qu’API COM ou en tant qu’API plate. Pour les clients non managés C++ qui sont prêts à recompiler leur code avec Visual Studio® .NET, il existe une troisième option : accéder directement aux fonctionnalités managées via l’interopérabilité C++. Des suggestions sur la façon et le moment d’utiliser ces options sont décrites dans cette section.

Accès direct à une API managée

Si un client non managé est écrit en C++, il peut être compilé avec le compilateur Visual Studio .NET C++ en tant qu'« image en mode mixte ». Une fois cette opération effectuée, le client non managé peut accéder directement à n’importe quelle API managée. Toutefois, certaines règles de codage s’appliquent à l’accès aux objets managés à partir de code non managé ; case activée la documentation C++ pour plus d’informations.

L’accès direct est l’option préférée, car elle ne nécessite aucune considération particulière de la part des développeurs d’API managées. Ils peuvent concevoir leur API managée conformément aux directives de conception d’API managées (DG) et être sûrs que l’API sera toujours accessible aux appelants non managés.

Exposition d’une API managée en tant qu’API COM

Chaque classe gérée publique peut être exposée à des clients non managés par le biais de l’interopérabilité COM. Ce processus est très facile à mettre en œuvre, car la couche d’interopérabilité COM prend en charge l’ensemble de la plomberie COM. Ainsi, par exemple, chaque classe managée semble implémenter IUnknown, IDispatch, ISupportErrorInfo et quelques autres interfaces COM standard.

Malgré le fait que l’exposition d’API managées en tant qu’API COM soit facile, les modèles objet MANAGÉ et COM sont très différents. Par conséquent, l’exposition de l’API managée à COM doit toujours être une décision de conception explicite. Certaines fonctionnalités disponibles dans le monde managé n’ont pas d’équivalent dans le monde COM et ne sont pas utilisables auprès des clients COM. Pour cette raison, il existe souvent des tensions entre les instructions de conception d’API managées (DG) et la compatibilité avec COM.

Si les clients COM sont importants, écrivez votre API managée conformément aux instructions de conception de l’API managée, puis écrivez un wrapper managé compatible COM léger autour de votre API managée qui sera exposée à COM.

Exposition d’une API managée en tant qu’API plate

Parfois, les clients non managés ne peuvent pas utiliser COM. Par exemple, elles peuvent déjà être écrites pour utiliser des API plates et ne peuvent pas être modifiées ou recompilées. C++ est le seul langage de haut niveau qui vous permet d’exposer des API managées en tant qu’API plates. Cela n’est pas aussi simple que d’exposer une API managée en tant qu’API COM. Il s’agit d’une technique très avancée qui nécessite une connaissance avancée de l’interopérabilité C++ et des différences entre les mondes managés et non managés.

Exposez votre API managée en tant qu’API plate uniquement si cela est absolument nécessaire. Si vous n’avez pas le choix, veillez à case activée la documentation C++ et à connaître toutes les limitations.

Arbre de décision pour l’exposition d’API managées

Figure 2 : Exposition de l’arbre de décision des API managées

Sécurité

Le Common Language Runtime est fourni avec un système de sécurité, Code Access Security (CAS), qui règle l’accès aux ressources protégées en fonction des informations sur l’origine d’un assembly. L’appel de code non managé présente un risque de sécurité majeur. Sans vérifications de sécurité appropriées, le code non managé peut manipuler n’importe quel état d’une application managée dans le processus CLR. Il est également possible d’appeler directement des ressources dans du code non managé, sans que ces ressources soient soumises à des vérifications d’autorisation CAS. Pour cette raison, toute transition vers du code non managé est considérée comme une opération hautement protégée et doit inclure un case activée de sécurité. Cette case activée de sécurité recherche l’autorisation de code non managée qui nécessite que l’assembly contenant la transition de code non managée, ainsi que tous les assemblys qui l’appellent, ait le droit d’appeler du code non managé.

Il existe certains scénarios d’interopérabilité limités dans lesquels des vérifications de sécurité complètes ne sont pas nécessaires et limiteraient indûment les performances ou l’étendue du composant. C’est le cas si une ressource exposée à partir d’un code non managé n’a aucune pertinence pour la sécurité (heure système, coordonnées de fenêtre, etc.), ou si la ressource est utilisée uniquement en interne dans l’assembly et n’est pas exposée publiquement à des appelants arbitraires. Dans ce cas, vous pouvez supprimer la case activée de sécurité complète pour l’autorisation de code non managé sur tous les appelants des API appropriées. Pour ce faire, appliquez l’attribut personnalisé SuppressUnmanagedCodeSecurity à la méthode ou à la classe interop correspondante. Notez que cela suppose une révision de sécurité minutieuse lorsque vous avez déterminé qu’aucun code partiellement approuvé ne pouvait exploiter ces API.

Fiabilité

Le code managé est conçu pour être plus fiable et robuste que le code non managé. Un exemple de fonctionnalité CLR qui promeut ces qualités est le garbage collection, qui s’occupe de libérer la mémoire inutilisée afin d’éviter les fuites de mémoire. Un autre exemple est la sécurité de type managé, qui est utilisé pour empêcher les erreurs de dépassement de mémoire tampon et d’autres erreurs liées au type.

Lorsque vous utilisez n’importe quel type de technologie d’interopérabilité, votre code peut ne pas être aussi fiable ou robuste que du code managé pur. Par exemple, vous devrez peut-être allouer manuellement de la mémoire non managée et n’oubliez pas de la libérer lorsque vous en avez terminé.

L’écriture de tout code d’interopérabilité non trivial nécessite la même attention à la fiabilité et à la robustesse que l’écriture de code non managé. Même si tout le code d’interopérabilité est écrit correctement, votre système sera aussi fiable que ses parties non managées.

Performances

À chaque transition du code managé vers du code non managé (et inversement), il y a une surcharge de performances. La surcharge dépend des types de paramètres utilisés. La couche d’interopérabilité CLR utilise trois niveaux d’optimisation des appels d’interopérabilité en fonction du type de transition et des types de paramètres : inlining juste-à-temps (JIT), stubs d’assembly compilés et stubs de marshaling interprétés (dans l’ordre du type d’appel le plus rapide à le plus lent).

Surcharge approximative pour un appel d’appel de plateforme : 10 instructions d’ordinateur (sur un processeur x86)

Surcharge approximative pour un appel d’interopérabilité COM : 50 instructions d’ordinateur (sur un processeur x86)

Le travail effectué par ces instructions est illustré dans les sections de l’annexe Appel d’une API plate : étape par étape et appel d’une API COM : pas à pas. En plus de s’assurer que le garbage collector ne bloque pas les threads non managés pendant l’appel et de gérer les conventions d’appel et les exceptions non managées, l’interopérabilité COM effectue un travail supplémentaire pour convertir l’appel sur le wrapper RCW (Runtime Callable Wrapper) actuel en pointeur d’interface COM approprié au contexte actuel.

Chaque appel d’interopérabilité entraîne une surcharge. Selon la fréquence à laquelle ces appels se produisent et l’importance du travail effectué à l’intérieur de l’implémentation de la méthode, la surcharge par appel peut aller de négligeable à très notable.

Sur la base de ces considérations, la liste suivante fournit des suggestions de performances générales qui peuvent vous être utiles :

  • Si vous contrôlez l’interface entre le code managé et le code non managé, rendez-la « segmentée » plutôt que « bavard » pour réduire le nombre total de transitions effectuées.

    Les interfaces bavardes sont des interfaces qui effectuent de nombreuses transitions sans effectuer de travail significatif de l’autre côté de la limite d’interopérabilité. Par exemple, les setters de propriétés et les getters sont bavards. Les interfaces segmentiques sont des interfaces qui n’effectuent que quelques transitions, et la quantité de travail effectuée de l’autre côté de la limite est importante. Par exemple, une méthode qui ouvre une connexion de base de données et récupère certaines données est fragmenté. Les interfaces segmentiques impliquent moins de transitions d’interopérabilité, de sorte que vous éliminez une surcharge de performances.

  • Évitez les conversions Unicode/ANSI si possible.

    La conversion de chaînes d’Unicode en ANSI et vice versa est une opération coûteuse. Par exemple, si des chaînes doivent être transmises, mais que leur contenu n’est pas important, vous pouvez déclarer un paramètre de chaîne en tant qu’IntPtr et le marshaleur d’interopérabilité n’effectuera aucune conversion.

  • Pour les scénarios hautes performances, la déclaration de paramètres et de champs en tant qu’IntPtr peut améliorer les performances, mais au détriment de la facilité d’utilisation et de la maintenance.

    Parfois, il est plus rapide d’effectuer un marshaling manuel à l’aide des méthodes disponibles sur la classe Marshal , plutôt que de s’appuyer sur le marshaling d’interopérabilité par défaut. Par exemple, si de grands tableaux de chaînes doivent être passés au-delà d’une limite d’interopérabilité, mais que seuls quelques éléments sont nécessaires, la déclaration du tableau en tant qu’IntPtr et l’accès manuel à ces quelques éléments uniquement seront beaucoup plus rapides.

  • Utilisez InAttribute et OutAttribute judicieusement pour réduire le marshaling inutile.

    Le marshaleur d’interopérabilité utilise des règles par défaut pour décider si un certain paramètre doit être marshalé avant l’appel et marshalé après l’appel. Ces règles sont basées sur le niveau d’indirection et le type de paramètre. Certaines de ces opérations peuvent ne pas être nécessaires en fonction de la sémantique de la méthode.

  • Utilisez SetLastError=false sur les signatures d’appel de plateforme uniquement si vous appelez Marshal.GetLastWin32Error par la suite.

    La définition de SetLastError=true sur les signatures d’appel de plateforme nécessite un travail supplémentaire de la couche d’interopérabilité pour conserver le dernier code d’erreur. Utilisez cette fonctionnalité uniquement lorsque vous vous appuyez sur ces informations et que vous l’utiliserez après avoir passé l’appel.

  • Si, et uniquement si, les appels non managés sont exposés de manière non exploitable, utilisez SuppressUnmanagedCodeSecurityAttribute pour réduire le nombre de vérifications de sécurité.

    Les vérifications de sécurité sont très importantes. Si votre API n’expose pas de ressources protégées ou d’informations sensibles, ou qu’elles sont bien protégées, des vérifications de sécurité approfondies peuvent entraîner une surcharge inutile. Toutefois, le coût de ne pas effectuer de case activée de sécurité est très élevé.

Annexe 1 : Dépassement de la limite d’interopérabilité

Appel d’une API plate : étape par étape

Figure 3. Appel d’une API plate

  1. Obtenez LoadLibrary et GetProcAddress.
  2. Générez un stub DllImport à partir de la signature contenant l’adresse cible.
  3. Envoyer (push) les registres appelés enregistrés.
  4. Configurez un cadre DllImport et envoyez-le sur la pile d’images.
  5. Si de la mémoire temporaire est allouée, initialisez une liste propre pour une libération rapide à la fin de l’appel.
  6. Marshaler les paramètres. (Cela peut allouer de la mémoire.)
  7. Modifiez le mode garbage collection de coopérative en mode préemptif, afin qu’un garbage collection puisse se produire à tout moment.
  8. Chargez l’adresse cible et appelez-la.
  9. Si le bit SetLastError est défini, appelez GetLastError et stockez le résultat dans une abstraction de thread stockée dans le stockage local des threads.
  10. Revenez au mode garbage collection coopératif.
  11. Si PreserveSig=false et la méthode ont retourné un échec HRESULT, lèvez une exception.
  12. Si aucune exception n’a été levée, propagez les paramètres hors et by-ref .
  13. Restaurez le pointeur de la pile étendue à sa valeur d’origine pour prendre en compte les arguments extraits de l’appelant.

Appel d’une API COM : étape par étape

Figure 4. Appel d’une API COM

  1. Créez un stub managé à non managé à partir de la signature.
  2. Envoyer (push) les registres appelés enregistrés.
  3. Configurez un cadre d’interopérabilité COM géré à non managé et envoyez-le sur la pile d’images.
  4. Réservez de l’espace pour les données temporaires utilisées pendant la transition.
  5. Si de la mémoire temporaire est allouée, initialisez une liste propre pour une libération rapide à la fin de l’appel.
  6. Effacer les indicateurs d’exception à virgule flottante (x86 uniquement).
  7. Marshaler les paramètres. (Cela peut allouer de la mémoire.)
  8. Récupérez le pointeur d’interface correct pour le contexte actuel à l’intérieur du wrapper d’appel d’exécution. Si le pointeur mis en cache ne peut pas être utilisé, appelez QueryInterface sur le composant COM pour l’obtenir.
  9. Modifiez le mode garbage collection de coopérative en mode préemptif, afin qu’un garbage collection puisse se produire à tout moment.
  10. À partir du pointeur vtable, indexez par le numéro d’emplacement, obtenez l’adresse cible et appelez-la.
  11. Appelez Release sur le pointeur d’interface si QueryInterface a été appelé précédemment.
  12. Revenez au mode garbage collection coopératif.
  13. Si la signature n’est pas marquée PreserveSig, case activée en cas d’échec HRESULT et lève une exception (potentiellement remplie d’informations IErrorInfo).
  14. Si aucune exception n’a été levée, propagez les paramètres hors et by-ref .
  15. Restaurez le pointeur de la pile étendue à la valeur d’origine pour prendre en compte les arguments déclenchés par l’appelant.

Appel d’une API managée à partir de COM : étape par étape

Figure 5. Appel d’une API managée à partir de COM

  1. Générez un stub non managé à géré à partir de la signature.
  2. Envoyer (push) les registres appelés enregistrés.
  3. Configurez une image COM Interop non managée et poussez-la sur la pile d’images.
  4. Réservez de l’espace pour les données temporaires utilisées pendant la transition.
  5. Modifiez le mode garbage collection de coopérative en mode préemptif afin qu’un garbage collection puisse se produire à tout moment.
  6. Récupérez le wrapper COM pouvant être appelé (CCW) à partir du pointeur d’interface.
  7. Récupérez l’objet managé à l’intérieur du CCW.
  8. Les domaines d’application de transition, si nécessaire.
  9. Si un domaine d’application est sans confiance totale, effectuez toutes les demandes de lien que la méthode peut avoir sur le domaine d’application cible.
  10. Si de la mémoire temporaire est allouée, initialisez une liste propre pour une libération rapide à la fin de l’appel.
  11. Marshaler les paramètres. (Cela peut allouer de la mémoire.)
  12. Recherchez la méthode gérée par la cible à appeler. (Cela implique le mappage des appels d’interface à l’implémentation cible.)
  13. Mettre en cache la valeur de retour. (S’il s’agit d’une valeur de retour à virgule flottante, obtenez-la à partir du registre à virgule flottante.)
  14. Revenez au mode garbage collection coopératif.
  15. Si une exception a été levée, extrayez son HRESULT pour retourner, puis appelez SetErrorInfo.
  16. Si aucune exception n’a été levée, propagez les paramètres hors et by-ref .
  17. Restaurez le pointeur de la pile étendue à la valeur d’origine pour prendre en compte les arguments déclenchés par l’appelant.

Annexe 2 : Ressources

Doit lire!.NET et COM : Guide d’interopérabilité complet par Adam Nathan

Interopérabilité avec du code non managé, Guide du développeur Microsoft .NET Framework

Exemples d’interopérabilité, Microsoft .NET Framework

Blog d’Adam Nathan

Blog de Chris Brumme

Annexe 3 : Glossaire des termes

AppDomain (Domaine d’application) Un domaine d’application peut être considéré comme similaire à un processus de système d’exploitation léger et est géré par le Common Language Runtime.
CCW (wrapper com callable) Type spécial de wrapper créé par la couche d’interopérabilité CLR autour d’objets managés activés à partir du code COM. Une instance CCW masque les différences entre les modèles d’objets gérés et COM en fournissant le marshaling des données, la gestion de la durée de vie, la gestion des identités, la gestion des erreurs, des transitions correctes d’appartement et de threading, et ainsi de suite. Les témoins ccw exposent les fonctionnalités d’objet managé de manière com-friendly sans exiger que l’implémenteur de code managé sache quoi que ce soit sur la plomberie COM.
CLR Le common language runtime.
Interopérabilité COM Service fourni par la couche d’interopérabilité CLR pour l’utilisation d’API COM à partir de code managé ou l’exposition d’API managées en tant qu’API COM à des clients non managés. L’interopérabilité COM est disponible dans tous les langages managés.
Interopérabilité C++ Service fourni par le compilateur de langage C++ et le CLR, il est utilisé pour mélanger directement du code managé et non managé dans le même fichier exécutable. L’interopérabilité C++ implique généralement l’inclusion de fichiers d’en-tête dans des API non managées et le respect de certaines règles de codage.
API plate complexe API qui ont des signatures difficiles à déclarer dans le langage managé. Par exemple, les méthodes avec des paramètres de structure de taille variable sont difficiles à déclarer, car il n’existe aucun concept équivalent dans le système de type managé.
Interop Terme général qui couvre tout type d’interopérabilité entre le code managé et non managé (également appelé « natif »). L’interopérabilité est l’un des nombreux services fournis par le CLR.
Assembly d’interopérabilité Type spécial d’assembly managé qui contient des équivalents de type managé pour les types COM contenus dans une bibliothèque de types. Généralement produit en exécutant l’outil Importer de bibliothèque de types (Tlbimp.exe) sur une bibliothèque de types.
Code managé Le code qui s’exécute sous le contrôle du CLR est appelé code managé. Par exemple, tout code écrit en C# ou Visual Basic .NET est du code managé.
Appel de plateforme Service fourni par la couche d’interopérabilité CLR pour appeler des API plates non managées à partir de code managé. L’appel de plateforme est disponible dans tous les langages managés.
RCW (runtime callable wapper) Type spécial de wrapper créé par la couche d’interopérabilité CLR autour d’objets COM activés à partir du code managé. Un modèle RCW masque les différences entre les modèles d’objets gérés et COM en fournissant le marshaling des données, la gestion de la durée de vie, la gestion des identités, la gestion des erreurs, des transitions correctes d’appartement et de threading, etc.
Code non managé Le code qui s’exécute en dehors du CLR est appelé « code non managé ». Les composants COM, les composants ActiveX et les fonctions d’API Win32 sont des exemples de code non managé.