Panoramica sull'interoperabilità sul codice gestito e non gestito

 

Sonja Keserovic, Program Manager
David Mortenson, Lead Software Design Engineer
Adam Nathan, Lead Software Design Engineer in Test

Microsoft Corporation

Ottobre 2003

Si applica a:
   Microsoft® .NET Framework
   Interoperabilità COM

Riepilogo: Questo articolo fornisce informazioni di base sull'interoperabilità tra codice gestito e non gestito e linee guida e procedure comuni per l'accesso e il wrapping di API non gestite dal codice gestito e per esporre le API gestite ai chiamanti non gestiti. Sono evidenziate anche considerazioni sulla sicurezza e sull'affidabilità, i dati sulle prestazioni e le procedure generali per i processi di sviluppo. (14 pagine stampate)

Prerequisiti: Il pubblico di destinazione per questo documento include sviluppatori e responsabili che devono prendere decisioni di alto livello su dove usare il codice gestito. A tale scopo, è utile comprendere come funziona l'interazione tra codice gestito e non gestito e come si applicano le linee guida correnti a scenari specifici.

Contenuto

Introduzione all'interoperabilità
Linee guida per l'interoperabilità
Security
Affidabilità
Prestazioni
Appendice 1: Superamento del limite di interoperabilità
Appendice 2: Risorse
Appendice 3: Glossario delle condizioni

Introduzione all'interoperabilità

Common Language Runtime (CLR) promuove l'interazione del codice gestito con componenti COM, servizi COM+, API Win32® e altri tipi di codice non gestito. I tipi di dati, i meccanismi di gestione degli errori, le regole di creazione e distruzione e le linee guida di progettazione variano tra modelli a oggetti gestiti e non gestiti. Per semplificare l'interoperabilità tra codice gestito e non gestito e per semplificare il percorso di migrazione, il livello di interoperabilità CLR nasconde le differenze tra questi modelli a oggetti da client e server.

L'interoperabilità ("interoperabilità") è bidirezionale, che rende possibile:

  • Chiamare le API non gestite dal codice gestito

    Questa operazione può essere eseguita sia per le API flat (esportazioni dll statiche, ad esempio l'API Win32, esposta da DLL come kernel32.dll e user32.dll) sia per le API COM (modelli a oggetti come quelli esposti da Microsoft® Word, Excel, Internet Explorer, ActiveX® Data Objects (ADO) e così via.

  • Esporre LE API gestite al codice non gestito

    Esempi di questa operazione includono la creazione di un componente aggiuntivo per un'applicazione basata su COM, ad esempio Windows Media® Player o l'incorporamento di un controllo di Windows Forms gestito in un modulo MFC.

Tre tecnologie complementari consentono queste interazioni gestite/non gestite:

  • Platform Invoke (talvolta definito P/Invoke) consente di chiamare qualsiasi funzione in qualsiasi linguaggio non gestito, purché la firma venga ridecorato nel codice sorgente gestito. È simile alla funzionalità fornita dall'istruzione Declare in Visual Basic® 6.0.
  • L'interoperabilità COM consente di chiamare i componenti COM in qualsiasi linguaggio gestito in modo simile all'uso di componenti gestiti normali e viceversa. L'interoperabilità COM è costituita da servizi di base forniti da CLR, oltre ad alcuni strumenti e API nello spazio dei nomi System.Runtime.InteropServices .
  • L'interoperabilità C++ (talvolta denominata It Just Works (IJW)) è una funzionalità specifica di C++, che consente l'uso diretto delle API flat e delle API COM, in quanto sono sempre state usate. Questo è più potente dell'interoperabilità COM, ma richiede molto più cura. Assicurarsi di controllare le risorse C++ prima di usare questa tecnologia.

Linee guida per l'interoperabilità

Chiamata di API non gestite dal codice gestito

Esistono diversi tipi di API non gestite e diversi tipi di tecnologie di interoperabilità disponibili per la chiamata. I suggerimenti su come e quando usare queste tecnologie sono descritti in questa sezione. Si noti che questi suggerimenti sono molto generali e non coprono ogni scenario. È consigliabile valutare attentamente gli scenari e applicare le procedure di sviluppo e/o le soluzioni che hanno senso per lo scenario.

Chiamata di API flat non gestite

Esistono due meccanismi per la chiamata in API flat non gestite dal codice gestito: tramite Platform Invoke (disponibile in tutti i linguaggi gestiti) o tramite l'interoperabilità C++ (disponibile in C++).

Prima di decidere di chiamare un'API flat usando una di queste tecnologie di interoperabilità, è necessario determinare se sono disponibili funzionalità equivalenti in .NET Framework. È consigliabile, se possibile, usare la funzionalità di .NET Framework anziché chiamare API non gestite.

Per chiamare solo alcuni metodi non gestiti o per chiamare API flat semplici, il suggerimento consiste nell'usare l'interoperabilità della piattaforma anziché l'interoperabilità C++. La scrittura di dichiarazioni di richiamo della piattaforma per le API flat semplici è semplice. CLR si occupa del caricamento della DLL e del marshalling di tutti i parametri. Anche il lavoro di scrittura di alcune dichiarazioni di richiamo della piattaforma per API flat complesse è trascurabile rispetto al costo dell'uso dell'interoperabilità C++ e l'introduzione di un nuovo modulo scritto in C++.

Per il wrapping di API flat complesse non gestite o per il wrapping di API flat non gestite che cambiano mentre il codice gestito è in fase di sviluppo, il suggerimento consiste nell'usare l'interoperabilità C++ invece di richiamare la piattaforma. Il livello C++ può essere molto sottile e il resto del codice gestito può essere scritto in qualsiasi altro linguaggio gestito di scelta. L'uso di una piattaforma richiama in questi scenari richiederebbe un sacco di sforzi per dichiarare di nuovo parti complesse dell'API nel codice gestito e mantenerle sincronizzate con le API non gestite. L'uso dell'interoperabilità C++ risolve questo problema consentendo l'accesso diretto alle API non gestite, che non richiede alcuna riscrittura, solo l'inclusione di un file di intestazione.

Chiamata di API COM

Esistono due modi per chiamare componenti COM dal codice gestito: tramite interoperabilità COM (disponibile in tutti i linguaggi gestiti) o tramite l'interoperabilità C++ (disponibile in C++).

Per chiamare componenti COM compatibili con OLE Automation, il suggerimento consiste nell'usare l'interoperabilità COM. CLR si occupa dell'attivazione dei componenti COM e del marshalling dei parametri.

Per chiamare i componenti COM in base al linguaggio IDL (Interface Definition Language), il suggerimento consiste nell'usare l'interoperabilità C++. Il livello C++ può essere molto sottile e il resto del codice gestito può essere scritto in qualsiasi linguaggio gestito. L'interoperabilità COM si basa sulle informazioni provenienti dalle librerie di tipi per eseguire chiamate di interoperabilità corrette, ma le librerie di tipi in genere non contengono tutte le informazioni presenti nei file IDL. L'uso dell'interoperabilità C++ risolve questo problema consentendo l'accesso diretto a queste API COM.

Per le aziende che hanno già fornito LE API COM, è importante considerare la spedizione di assembly di interoperabilità primari (PIA) per queste API, rendendoli così facili da usare per i client gestiti.

Albero delle decisioni per la chiamata di API non gestite

Figura 1. Chiamata dell'albero delle decisioni delle API non gestite

Esposizione di API gestite a codice non gestito

Esistono due modi principali per esporre un'API gestita ai chiamanti puramente non gestiti: come API COM o come API flat. Per i client non gestiti C++ che sono disposti a ricompilare il codice con Visual Studio® .NET, è disponibile una terza opzione: accesso diretto alle funzionalità gestite tramite interoperabilità C++. I suggerimenti su come e quando usare queste opzioni sono descritti in questa sezione.

Accesso diretto a un'API gestita

Se un client non gestito viene scritto in C++, può essere compilato con il compilatore .NET C++ di Visual Studio come "immagine in modalità mista". Al termine, il client non gestito può accedere direttamente a qualsiasi API gestita. Tuttavia, alcune regole di codifica si applicano all'accesso a oggetti gestiti da codice non gestito; controllare la documentazione di C++ per altri dettagli.

L'accesso diretto è l'opzione preferita poiché non richiede alcuna considerazione speciale da parte degli sviluppatori di API gestite. Possono progettare l'API gestita in base alle linee guida di progettazione api gestite (DG) e assicurarsi che l'API sia ancora accessibile ai chiamanti non gestiti.

Esposizione di un'API gestita come API COM

Ogni classe gestita pubblica può essere esposta ai client non gestiti tramite l'interoperabilità COM. Questo processo è molto semplice da implementare, perché il livello di interoperabilità COM si occupa di tutti gli impianti idraulici COM. Ad esempio, ogni classe gestita sembra implementare IUnknown, IDispatch, ISupportErrorInfo e alcune altre interfacce COM standard.

Nonostante il fatto che l'esposizione delle API gestite come API COM è facile, gestita e modelli a oggetti COM sono molto diversi. Pertanto, l'esposizione dell'API gestita a COM deve essere sempre una decisione di progettazione esplicita. Alcune funzionalità disponibili nel mondo gestito non hanno alcun equivalente nel mondo COM e non saranno utilizzabili dai client COM. A causa di questo, spesso c'è tensione tra linee guida di progettazione API gestite (DG) e compatibilità con COM.

Se i client COM sono importanti, scrivere l'API gestita in base alle linee guida di progettazione dell'API gestita e quindi scrivere un wrapper gestito com sottile intorno all'API gestita che verrà esposta a COM.

Esposizione di un'API gestita come API flat

A volte i client non gestiti non possono usare COM. Ad esempio, potrebbero essere già scritti per usare API flat e non possono essere modificate o ricompilate. C++ è l'unico linguaggio di alto livello che consente di esporre LE API gestite come API flat. Questa operazione non è semplice come esporre un'API gestita come API COM. È una tecnica molto avanzata che richiede conoscenze avanzate dell'interoperabilità C++ e le differenze tra i mondi gestiti e non gestiti.

Esporre l'API gestita come API flat solo se assolutamente necessario. Se non si ha scelta, assicurarsi di controllare la documentazione C++ e di essere completamente consapevoli di tutte le limitazioni.

Albero delle decisioni per l'esposizione delle API gestite

Figura 2. Esposizione dell'albero delle decisioni delle API gestite

Sicurezza

Common Language Runtime viene fornito con un sistema di sicurezza, Code Access Security (CAS), che regola l'accesso alle risorse protette in base alle informazioni sull'origine di un assembly. La chiamata di codice non gestito presenta un rischio di sicurezza importante. Senza controlli di sicurezza appropriati, il codice non gestito potrebbe modificare qualsiasi stato di qualsiasi applicazione gestita nel processo CLR. È anche possibile chiamare direttamente le risorse nel codice non gestito, senza che queste risorse siano soggette a controlli delle autorizzazioni CAS. Per questo motivo, qualsiasi transizione al codice non gestito viene considerata un'operazione altamente protetta e deve includere un controllo di sicurezza. Questo controllo di sicurezza cerca l'autorizzazione per il codice non gestito che richiede l'assembly contenente la transizione del codice non gestito, nonché tutti gli assembly che vi chiamano, per avere il diritto di richiamare effettivamente codice non gestito.

Esistono alcuni scenari di interoperabilità limitati in cui i controlli di sicurezza completi non sono necessari e limitano eccessivamente le prestazioni o l'ambito del componente. In questo caso, se una risorsa esposta da codice non gestito non ha rilevanza per la sicurezza (tempo di sistema, coordinate della finestra e così via) o la risorsa viene usata solo internamente nell'assembly e non viene esposta pubblicamente ai chiamanti arbitrari. In questi casi, è possibile eliminare il controllo di sicurezza completo per l'autorizzazione del codice non gestito per tutti i chiamanti delle API pertinenti. A tale scopo, applicare l'attributo personalizzato SuppressUnmanagedCodeSecurity al rispettivo metodo o classe di interoperabilità. Si noti che si presuppone un'attenta verifica della sicurezza in cui è stato determinato che nessun codice parzialmente attendibile potrebbe sfruttare tali API.

Affidabilità

Il codice gestito è progettato per essere più affidabile e affidabile rispetto al codice non gestito. Un esempio di funzionalità CLR che promuove queste qualità è Garbage Collection, che si occupa di liberare memoria inutilizzata per evitare perdite di memoria. Un altro esempio è la sicurezza dei tipi gestiti, che viene usata per evitare errori di sovraccarico del buffer e altri errori correlati al tipo.

Quando si usa qualsiasi tipo di tecnologia di interoperabilità, il codice potrebbe non essere affidabile o affidabile come codice gestito puro. Ad esempio, potrebbe essere necessario allocare manualmente la memoria non gestita e ricordarsi di liberarla al termine dell'operazione.

La scrittura di codice di interoperabilità non semplice richiede la stessa attenzione all'affidabilità e all'affidabilità della scrittura di codice non gestito. Anche quando tutto il codice di interoperabilità viene scritto correttamente, il sistema sarà affidabile solo come le parti non gestite.

Prestazioni

Con ogni transizione dal codice gestito al codice non gestito (e viceversa), si verifica un sovraccarico delle prestazioni. La quantità di overhead dipende dai tipi di parametri usati. Il livello di interoperabilità CLR usa tre livelli di ottimizzazione delle chiamate di interoperabilità in base al tipo di transizione e ai tipi di parametro: l'inlining JIT (Just-In-Time), gli stub di assembly compilati e gli stub di marshalling interpretati (in ordine di tipo più veloce e lento di chiamata).

Overhead approssimativo per una chiamata platform invoke: 10 istruzioni del computer (in un processore x86)

Overhead approssimativo per una chiamata di interoperabilità COM: 50 istruzioni sul computer (in un processore x86)

Il lavoro svolto da queste istruzioni è illustrato nelle sezioni appendice Chiamata di un'API flat: passaggio per passaggio e chiamata di un'API COM: passo per passo. Oltre a garantire che il Garbage Collector non blocchi i thread non gestiti durante la chiamata e gestisca le convenzioni di chiamata e le eccezioni non gestite, l'interoperabilità COM esegue operazioni aggiuntive per convertire la chiamata sul wrapper chiamabile di runtime corrente (RCW) in un puntatore di interfaccia COM appropriato al contesto corrente.

Ogni chiamata di interoperabilità comporta un sovraccarico. A seconda della frequenza con cui si verificano queste chiamate e del significato del lavoro svolto all'interno dell'implementazione del metodo, il sovraccarico per chiamata può variare da trascurabile a molto evidente.

In base a queste considerazioni, l'elenco seguente fornisce alcuni suggerimenti generali sulle prestazioni che potrebbero risultare utili:

  • Se si controlla l'interfaccia tra codice gestito e non gestito, renderla "in blocchi" anziché "chiacchiere", per ridurre il numero totale di transizioni effettuate.

    Le interfacce chatty sono interfacce che eseguono molte transizioni senza eseguire alcun lavoro significativo sull'altro lato del limite di interoperabilità. Ad esempio, i setter di proprietà e i getter sono chiacchiere. Le interfacce in blocchi sono interfacce che eseguono solo alcune transizioni e la quantità di lavoro eseguita dall'altro lato del limite è significativa. Ad esempio, un metodo che apre una connessione al database e recupera alcuni dati è in blocchi. Le interfacce in blocchi comportano un minor numero di transizioni di interoperabilità, in modo da eliminare un sovraccarico delle prestazioni.

  • Evitare conversioni Unicode/ANSI, se possibile.

    La conversione di stringhe da Unicode a ANSI e viceversa è un'operazione costosa. Ad esempio, se è necessario passare stringhe, ma il relativo contenuto non è importante, è possibile dichiarare un parametro stringa come IntPtr e il gestore di marshalling di interoperabilità non eseguirà conversioni.

  • Per gli scenari ad alte prestazioni, la dichiarazione di parametri e campi come IntPtr può migliorare le prestazioni, anche se a scapito della facilità d'uso e della manutenibilità.

    A volte è più veloce eseguire il marshalling manuale usando i metodi disponibili nella classe Marshal , anziché basarsi sul marshalling di interoperabilità predefinito. Ad esempio, se è necessario passare matrici di stringhe di grandi dimensioni attraverso un limite di interoperabilità, ma saranno necessari solo alcuni elementi, dichiarando la matrice come IntPtr e accedendo solo a questi pochi elementi manualmente sarà molto più veloce.

  • Usare InAttribute e OutAttribute in modo saggio per ridurre il marshalling non necessario.

    Il gestore di marshalling di interoperabilità usa regole predefinite quando si decide se è necessario effettuare il marshalling di un determinato parametro prima della chiamata e effettuare il marshalling dopo la chiamata. Queste regole si basano sul livello di riferimento indiretto e sul tipo di parametro. Alcune di queste operazioni potrebbero non essere necessarie a seconda della semantica del metodo.

  • Usare SetLastError=false nelle firme platform invoke solo se successivamente chiamerai Marshal.GetLastWin32Error .

    L'impostazione di SetLastError=true nelle firme platform invoke richiede ulteriori operazioni dal livello di interoperabilità per mantenere l'ultimo codice di errore. Usare questa funzionalità solo quando si fa affidamento su queste informazioni e la si userà dopo aver eseguito la chiamata.

  • Se e solo se le chiamate non gestite vengono esposte in modo non sfruttabile, usare SuppressUnmanagedCodeSecurityAttribute per ridurre il numero di controlli di sicurezza.

    I controlli di sicurezza sono molto importanti. Se l'API non espone risorse protette o informazioni riservate o se sono ben protette, i controlli di sicurezza estesi potrebbero comportare un sovraccarico non necessario. Tuttavia, il costo di non eseguire alcun controllo di sicurezza è molto elevato.

Appendice 1: Superamento del limite di interoperabilità

Chiamata di un'API flat: procedura dettagliata

Figura 3. Chiamata di un'API flat

  1. Ottenere LoadLibrary e GetProcAddress.
  2. Compilare uno stub DllImport dalla firma contenente l'indirizzo di destinazione.
  3. Eseguire il push dei registri salvati dal chiamato.
  4. Configurare un frame DllImport ed eseguirne il push nello stack di frame.
  5. Se la memoria temporanea viene allocata, inizializzare un elenco di pulizia per liberare rapidamente al termine della chiamata.
  6. Parametri di marshalling. Questa operazione potrebbe allocare memoria.
  7. Modificare la modalità Garbage Collection da cooperativa a preemptive, in modo che un'operazione di Garbage Collection possa verificarsi in qualsiasi momento.
  8. Caricare l'indirizzo di destinazione e chiamarlo.
  9. Se il bit SetLastError è impostato, chiamare GetLastError e archiviare il risultato in un'astrazione del thread archiviata in Archiviazione locale thread.
  10. Tornare alla modalità di Garbage Collection cooperativa.
  11. Se PreserveSig=false e il metodo ha restituito un errore HRESULT, generare un'eccezione.
  12. Se non è stata generata alcuna eccezione, propagare nuovamente i parametri e per riferimento .
  13. Ripristinare il puntatore dello stack esteso al valore originale in modo da tenere conto degli argomenti di chiamata.

Chiamata di un'API COM: procedura dettagliata

Figura 4. Chiamata di un'API COM

  1. Creare uno stub gestito-non gestito dalla firma.
  2. Eseguire il push dei registri salvati dal chiamato.
  3. Configurare un frame di interoperabilità COM gestito-non gestito ed eseguirne il push nello stack di frame.
  4. Riservare spazio per i dati temporanei usati durante la transizione.
  5. Se la memoria temporanea viene allocata, inizializzare un elenco di pulizia per liberare rapidamente al termine della chiamata.
  6. Cancellare i flag di eccezione a virgola mobile (solo x86).
  7. Parametri di marshalling. Questa operazione potrebbe allocare memoria.
  8. Recuperare il puntatore di interfaccia corretto per il contesto corrente all'interno del wrapper chiamabile di runtime. Se il puntatore memorizzato nella cache non può essere utilizzato, chiamare QueryInterface nel componente COM per ottenerlo.
  9. Modificare la modalità Garbage Collection da cooperativa a preemptive, in modo che un'operazione di Garbage Collection possa verificarsi in qualsiasi momento.
  10. Dal puntatore della tabella virtuale, indicizzare in base al numero di slot, ottenere l'indirizzo di destinazione e chiamarlo.
  11. Call Release sul puntatore dell'interfaccia se QueryInterface è stato chiamato in precedenza.
  12. Tornare alla modalità di Garbage Collection cooperativa.
  13. Se la firma non è contrassegnata come PreserveSig, verificare l'errore HRESULT e generare un'eccezione (potenzialmente compilata con informazioni IErrorInfo ).
  14. Se non è stata generata alcuna eccezione, propagare nuovamente i parametri e per riferimento .
  15. Ripristinare il puntatore dello stack esteso al valore originale in modo da tenere in considerazione gli argomenti di tipo caller-popped.

Chiamata di un'API gestita da COM: procedura dettagliata

Figura 5. Chiamata di un'API gestita da COM

  1. Compilare uno stub non gestito dalla firma.
  2. Eseguire il push dei registri salvati dal chiamato.
  3. Configurare un frame di interoperabilità COM non gestito e eseguirne il push nello stack di frame.
  4. Riservare spazio per i dati temporanei usati durante la transizione.
  5. Modificare la modalità Garbage Collection da cooperativa a preemptive in modo che un'operazione di Garbage Collection possa verificarsi in qualsiasi momento.
  6. Recuperare il wrapper chiamabile COM (CCW) dal puntatore all'interfaccia.
  7. Recuperare l'oggetto gestito all'interno del CCW.
  8. Eseguire la transizione dei domini app, se necessario.
  9. Se un dominio app non è attendibile, eseguire qualsiasi richiesta di collegamento che il metodo potrebbe avere rispetto al dominio app di destinazione.
  10. Se la memoria temporanea viene allocata, inizializzare un elenco di pulizia per liberare rapidamente al termine della chiamata.
  11. Parametri di marshalling. Questa operazione potrebbe allocare memoria.
  12. Trovare il metodo gestito dalla destinazione da chiamare. Questo implica il mapping delle chiamate di interfaccia all'implementazione di destinazione.
  13. Memorizzare nella cache il valore restituito. Se si tratta di un valore restituito a virgola mobile, recuperarlo dal registro a virgola mobile.
  14. Tornare alla modalità di Garbage Collection cooperativa.
  15. Se è stata generata un'eccezione, estrarre il valore HRESULT da restituire e chiamare SetErrorInfo.
  16. Se non è stata generata alcuna eccezione, propagare nuovamente i parametri e per riferimento .
  17. Ripristinare il puntatore dello stack esteso al valore originale in modo da tenere in considerazione gli argomenti di tipo caller-popped.

Appendice 2: Risorse

Deve leggere!.NET e COM: Guida completa all'interoperabilità di Adam Nathan

Interoperabilità con codice non gestito, Guida per gli sviluppatori di Microsoft .NET Framework

Esempi di interoperabilità, Microsoft .NET Framework

Blog di Adam Nathan

Blog di Chris Brumme

Appendice 3: Glossario dei termini

AppDomain (dominio applicazione) Un dominio applicazione può essere considerato simile a un processo leggero del sistema operativo ed è gestito da Common Language Runtime.
CCW (wrapper chiamabile COM) Tipo speciale di wrapper creato dal livello di interoperabilità CLR per gli oggetti gestiti attivati dal codice COM. Un CCW nasconde le differenze tra i modelli a oggetti gestiti e COM fornendo il marshalling dei dati, la gestione della durata, la gestione delle identità, la gestione degli errori, le transizioni di apartment e threading corrette e così via. Le workstation CCW espongono la funzionalità degli oggetti gestiti in modo intuitivo senza richiedere all'implementatore del codice gestito di conoscere qualsiasi elemento sull'impianto idraulico COM.
CLR Common Language Runtime
interoperabilità COM Il servizio fornito dal livello di interoperabilità CLR per l'uso delle API COM dal codice gestito o l'esposizione di API gestite come API COM a client non gestiti. L'interoperabilità COM è disponibile in tutti i linguaggi gestiti.
Interoperabilità C++ Il servizio fornito dal compilatore di linguaggio C++ e CLR, viene usato per combinare direttamente codice gestito e non gestito nello stesso file eseguibile. L'interoperabilità C++ implica in genere l'inclusione di file di intestazione in API non gestite e la seguente regola di codifica.
API flat complessa API con firme difficili da dichiarare nel linguaggio gestito. Ad esempio, i metodi con parametri di struttura delle dimensioni variabili sono difficili da dichiarare perché non esiste un concetto equivalente nel sistema di tipi gestiti.
Interoperabilità Termine generale che copre qualsiasi tipo di interoperabilità tra codice gestito e non gestito (detto anche "nativo"). L'interoperabilità è uno dei numerosi servizi forniti da CLR.
Assembly di interoperabilità Tipo speciale di assembly gestito che contiene equivalenti di tipi gestiti per i tipi COM contenuti in una libreria dei tipi. In genere prodotto eseguendo lo strumento di importazione libreria dei tipi (Tlbimp.exe) in una libreria dei tipi.
Codice gestito Il codice in esecuzione sotto il controllo di CLR viene chiamato codice gestito. Ad esempio, qualsiasi codice scritto in C# o Visual Basic .NET è codice gestito.
Platform Invoke Il servizio fornito dal livello di interoperabilità CLR per chiamare LE API flat non gestite dal codice gestito. Platform invoke è disponibile in tutti i linguaggi gestiti.
RCW (wapper chiamabile in fase di esecuzione) Tipo speciale di wrapper creato dal livello di interoperabilità CLR intorno agli oggetti COM attivati dal codice gestito. Un RCW nasconde le differenze tra i modelli a oggetti GESTITI e COM fornendo il marshalling dei dati, la gestione della durata, la gestione delle identità, la gestione degli errori, le transizioni di apartment e threading corrette e così via.
Codice non gestito Il codice eseguito all'esterno di CLR viene definito "codice non gestito". I componenti COM, i componenti ActiveX e le funzioni API Win32 sono esempi di codice non gestito.