Condividi tramite


Panoramica dell'interoperabilità del codice gestito/non gestito

 

Sonja Keserovič, Program Manager
David Mortenson, responsabile del design software
Adam Nathan, responsabile del design software 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 l'esposizione di API gestite a chiamanti non gestiti. Vengono 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 gruppo di destinatari di questo documento include sviluppatori e responsabili che devono prendere decisioni di alto livello su dove usare il codice gestito. A tale scopo, è utile comprendere il funzionamento dell'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à
Sicurezza
Affidabilità
Prestazione
Appendice 1: Superamento del limite di interoperabilità
Appendice 2: Risorse
Appendice 3: Glossario dei termini

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 i 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 consente di:

  • Chiamare in API non gestite dal codice gestito

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

  • Esporre api gestite a codice non gestito

    Alcuni 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 Windows Form 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 dichiarata nuovamente 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++ (nota anche come It Just Works (IJW)) è una funzionalità specifica di C++, che consente l'uso diretto di API flat e API COM, perché sono sempre state usate. Questo è più potente dell'interoperabilità COM, ma richiede molta più attenzione. Assicurarsi di controllare le risorse C++ prima di usare questa tecnologia.

Linee guida per l'interoperabilità

Chiamata di API non gestite da 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 tutti gli scenari. È consigliabile valutare attentamente gli scenari e applicare procedure di sviluppo e/o soluzioni appropriate per lo scenario.

Chiamata di API flat non gestite

Esistono due meccanismi per chiamare 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 in .NET Framework sono disponibili funzionalità equivalenti. È consigliabile, quando 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 platform invoke anziché l'interoperabilità C++. La scrittura di dichiarazioni platform invoke per api flat semplici è semplice. CLR si occuperà del caricamento della DLL e del marshalling di tutti i parametri. Anche il lavoro di scrittura di alcune dichiarazioni di platform invoke per API flat complesse è trascurabile rispetto al costo dell'uso dell'interoperabilità C++ e l'introduzione di un nuovo modulo completo scritto in C++.

Per il wrapping di API flat non gestite complesse 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++ anziché platform invoke. 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 platform invoke in questi scenari richiederebbe molto impegno per dichiarare nuovamente 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 richiedono la riscrittura, ma 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 l'automazione OLE, il suggerimento consiste nell'usare l'interoperabilità COM. CLR si occuperà dell'attivazione dei componenti COM e del marshalling dei parametri.

Per chiamare i componenti COM basati su 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 delle librerie dei tipi per effettuare chiamate di interoperabilità corrette, ma le librerie dei 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 possiedono API COM già spedite, è importante considerare la spedizione di assembly di interoperabilità primari (PIA) per queste API, semplificando così l'utilizzo per i client gestiti.

Albero delle decisioni per la chiamata di API non gestite

Figura 1. Chiamata all'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: l'accesso diretto alle funzionalità gestite tramite l'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 C++ di Visual Studio .NET 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; Per altri dettagli, vedere la documentazione di C++.

L'accesso diretto è l'opzione preferita perché non richiede alcuna considerazione speciale da parte degli sviluppatori di API gestite. Possono progettare l'API gestita in base alle linee guida di progettazione dell'API gestita (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, ISupportErrorInfoe alcune altre interfacce COM standard.

Nonostante il fatto che l'esposizione di API gestite come API COM è semplice, gestita e i 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 equivalenti nel mondo COM e non saranno utilizzabili dai client COM. Per questo motivo, spesso c'è tensione tra le linee guida di progettazione delle API gestite (DG) e la 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 thin wrapper gestito compatibile con COM per l'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 modificati o ricompilati. C++ è l'unico linguaggio di alto livello che consente di esporre LE API gestite come API flat. Questa operazione non è semplice come l'esposizione di un'API gestita come API COM. Si tratta di 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 di C++ e di essere completamente a conoscenza di tutte le limitazioni.

Albero delle decisioni per l'esposizione di 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 importante per la sicurezza. 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 lo chiamano, per avere il diritto di richiamare effettivamente il 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. Questo è il 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 il SuppressUnmanagedCodeSecurity attributo personalizzato 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 gestita, 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 sue parti non gestite.

Prestazione

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 più 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 del computer (in un processore x86)

Il lavoro svolto da queste istruzioni è illustrato nelle sezioni dell'appendice Chiamata di un'API flat: passaggio per passaggio e chiamata di un'API COM: procedura dettagliata. 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 funziona in modo aggiuntivo 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é "chatty", 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 chunky sono interfacce che eseguono solo alcune transizioni e la quantità di lavoro svolto dall'altro lato del limite è significativa. Ad esempio, un metodo che apre una connessione di database e recupera alcuni dati è in blocchi. Le interfacce chunky comportano un minor numero di transizioni di interoperabilità, quindi si elimina un sovraccarico delle prestazioni.

  • Evitare le 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à alcuna conversione.

  • Per scenari ad alte prestazioni, dichiarare 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 metodi disponibili nella classe Marshal, anziché basarsi sul marshalling predefinito dell'interoperabilità. 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 saggiamente 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 su platform invoke signatures solo se in seguito 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 effettuato 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 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 un DllImport stub dalla firma contenente l'indirizzo di destinazione.
  3. Eseguire il push dei registri salvati tramite 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. Questo 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 setLastError bit è impostato, chiamare GetLastError e archiviare il risultato in un'astrazione del thread archiviata in Archiviazione locale del thread.
  10. Tornare alla modalità di Garbage Collection cooperativa.
  11. Se PreserveSig=false e il metodo ha restituito un HRESULT di errore, generare un'eccezione.
  12. Se non è stata generata alcuna eccezione, di back-propagate e parametri di di riferimento.
  13. Ripristinare il puntatore dello stack esteso al valore originale per tenere conto degli argomenti di cui è stato rilevato il chiamante.

Chiamata di un'API COM: procedura dettagliata

Figura 4. Chiamata di un'API COM

  1. Creare uno stub gestito da gestito a non gestito dalla firma.
  2. Eseguire il push dei registri salvati tramite chiamato.
  3. Configurare un frame di interoperabilità COM gestito-non gestito ed eseguirne il push nello stack di fotogrammi.
  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. Questo potrebbe allocare memoria.
  8. Recuperare il puntatore di interfaccia corretto per il contesto corrente all'interno del wrapper chiamabile di runtime. Se non è possibile utilizzare il puntatore memorizzato nella cache, chiamare QueryInterface sul 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 vtable, indicizzare in base al numero di slot, ottenere l'indirizzo di destinazione e chiamarlo.
  11. Chiamare Release sul puntatore all'interfaccia se queryInterface è stato chiamato in precedenza.
  12. Tornare alla modalità di Garbage Collection cooperativa.
  13. Se la firma non è contrassegnata PreserveSig, verificare l'errore HRESULT e generare un'eccezione (potenzialmente compilata con informazioni IErrorInfo).
  14. Se non è stata generata alcuna eccezione, di back-propagate e parametri di di riferimento.
  15. Ripristinare il puntatore dello stack esteso al valore originale in modo da tenere conto degli argomenti verificati dal chiamante.

Chiamata di un'API gestita da COM: Procedura dettagliata

Figura 5. Chiamata di un'API gestita da COM

  1. Creare uno stub da non gestito a gestito dalla firma.
  2. Eseguire il push dei registri salvati tramite chiamato.
  3. Configurare un frame di interoperabilità COM non gestito e eseguirne il push nello stack di fotogrammi.
  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 dell'interfaccia.
  7. Recuperare l'oggetto gestito all'interno del CCW.
  8. Eseguire la transizione dei domini app, se necessario.
  9. Se un dominio app è senza attendibilità completa, 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. Questo potrebbe allocare memoria.
  12. Trovare il metodo gestito di destinazione da chiamare. Questo comporta il mapping delle chiamate dell'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 relativo HRESULT da restituire e chiamare SetErrorInfo.
  16. Se non è stata generata alcuna eccezione, di back-propagate e parametri di di riferimento.
  17. Ripristinare il puntatore dello stack esteso al valore originale in modo da tenere conto degli argomenti verificati dal chiamante.

Appendice 2: Risorse

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

l'interoperabilità con codice non gestito, Guida per 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 (com callable wrapper) Tipo speciale di wrapper creato dal livello di interoperabilità CLR intorno agli oggetti gestiti attivati dal codice COM. Un CCW nasconde le differenze tra i modelli a oggetti COM e gestiti 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 CCWs espongono la funzionalità degli oggetti gestiti in modo descrittivo senza richiedere all'implementatore del codice gestito di conoscere qualcosa sul plumbing 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 del linguaggio C++ e da CLR, viene usato per combinare direttamente il 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 l'esecuzione di determinate regole di codifica.
API flat complessa API con firme difficili da dichiarare nel linguaggio gestito. Ad esempio, i metodi con parametri della struttura di dimensioni variabili sono difficili da dichiarare poiché 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 codice "nativo"). L'interoperabilità è uno dei numerosi servizi offerti 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 utilità di importazione della libreria dei tipi (Tlbimp.exe) in una libreria dei tipi.
codice gestito Il codice in esecuzione sotto il controllo di CLR è denominato codice gestito. Ad esempio, qualsiasi codice scritto in C# o Visual Basic .NET è codice gestito.
Platform Invoke Servizio fornito dal livello di interoperabilità CLR per chiamare API flat non gestite dal codice gestito. Platform invoke è disponibile in tutte le lingue gestite.
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 COM e gestiti 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.