Il .NET Framework presenta un ambiente runtime, il CLR ( Common Language Runtime ), comune a tutti i linguaggi che lo supportano. I linguaggi .NET producono una volta compilati, uno pseudo assembly, il MSIL ( Microsoft Intermediate Language ), che il CLR traduce in codice macchina e lo esegue. Più precisamente questo codice intermedio è gestito ( managed ) da un thread esterno che viene eseguito in contemporanea e che effettua una serie di operazioni tra cui l’allocazione e la disallocazione degli oggetti in memoria.
Il compilatore C++ di Microsoft presenta queste caratteristiche:
- Compilare codice C++ in linguaggio macchina
- Compilare codice Managed C++ in linguaggio MSIL
- Fornire un wrapper .NET a sorgenti C++ di fatto permettendo loro di essere compilati in MSIL
- Offrire agli sviluppatori C++ la possibilità di utilizzare la BCL ( libreria di classi .NET )
La terza caratteristica è nota col nome di “It Just Works!” che potremmo tradurre in “Funziona proprio!”. Facciamo una prova compilando il classico “HelloWorld” in codice nativo e poi in MSIL.
#include <iostream> using namespace std; void main(int, char**) { string hello = "Ciao Mondo!"; cout << hello.c_str() << endl; }
Compiliamo la prima volta in codice nativo con il comando cl hello.cpp, otterremo un file oggetto e l’eseguibile che lanciamo e vediamo che il tempo di esecuzione è pressoché istantaneo, come è legittimo per un eseguibile in codice nativo. Se ora compiliamo il codice in MSIL con il comando cl /clr hello.cpp, noteremo che verrà creato un file eseguibile, un file oggetto ed il manifesto. Se eseguiamo hello.exe, occorre circa un secondo affinché l’applicazione sia eseguita, questo perché il programma carica il CLR, che ha il compito di compilarlo, ma dopo la prima esecuzione la velocità torna ad essere buona, anche se non la stessa del codice nativo.
Un eseguibile può contenere al suo interno sia parti managed, eseguite dal CLR, sia parti unmanaged, eseguite direttamente dal processore senza l’intermediazione del CLR.
Il CLS ( Common Language Specification ) è la specifica Microsoft seguendo la quale è possibile inventare o adattare un linguaggio esistente al .NET Framework, come per esempio VB.NET, C#, Eiffel#, Jscript. Il Managed C++ è C++ con alcune estensioni alla sintassi che gli permettono di essere un linguaggio CLS compliant e di utilizzare pienamente il supporto del CLR. Il punto fondamentale è che l’utilizzo del CLR ha senso quando si desidera utilizzare le features offerte dal .NET come la gestione della memoria o l’exception handling. Certo che il linguaggio C++ si discosta molto dalla filosofia del CLS, ad esempio non sono supportati i template o l’ereditarietà multipla, per questo un programma scritto in C++ non è automaticamente compatibile con il Managed C++.
La mia personalissima conclusione è che portare progetti da codice nativo a managed non sia una mossa azzeccata, mentre utilizzare codice misto per inserire alcune caratteristiche del .NET è senza dubbio qualcosa che vedo meglio, ma comunque per nuovi progetti vedo di buon occhio l’utilizzo del C#, che risulta più veloce per sviluppare delle applicazioni su piattaforma .NET.