Sinistra <- Duplicazione di un sistema - Indice Generale - Copertina - Installazione e configurazione di un server Linux -> Destra

Sistemi Liberi


Mono

di Gabriele Pranovi

L'articolo...

Descrive il progetto Mono, un porting del framework .net in ambiente Linux (e non solo). Nell'articolo vengono descritti gli strumenti forniti dal progetto e vengono dati alcuni semplici esempi di applicazioni console, windows form e gtk#.



Perché Mono

Mono riunisce molti degli aspetti che si possono trovare in un moderno linguaggio di programmazione orientato agli oggetti. Uno dei vantaggi principali è il fatto che il codice sorgente viene compilato in un linguaggio intermedio noto come CLI (Linguaggio Comune Intermedio) ed eseguito all'interno di un ambiente controllato. Il codice così eseguito prende il nome di Codice Gestito. L'esecuzione di codice gestito offre vari vantaggi, molti dei quali saranno già noti a chi programma in Java o in linguaggi di scripting.

Mono facilita anche il riuso di codice esistente tutelando eventuali investimenti pregressi. L'infrastruttura P/Invoke permette infatti l'accesso a tutti i metodi inclusi in librerie dinamiche (dll) esistenti, con poche righe di codice e in modo abbastanza elementare.

Il maggior vantaggio di Mono è però la riduzione dei tempi di sviluppo software. C#, ad esempio, ha una curva di apprendimento ridotta per i programmatori che vengono dal mondo C/C++ o Java, in quanto condivide con tali linguaggi terminologia OOP e sintassi. In più aggiunge alcune funzionalità che riducono sensibilmente i tempi di sviluppo: l'uso di Delegati ed Eventi, di Proprietà ed Interfacce sono solo alcuni esempi.

Contrariamente a quanto si può pensare, infine, l'esecuzione di codice CIL all'interno della macchina virtuale mono non è affatto lenta. Mono utilizza un JIT (un compilatore just in time) per tradurre il linguaggio bytecode intermedio in codice macchina. L'evoluzione del jitter e il suo continuo sviluppo ne garantiscono prestazioni simili se non superiori a quello utilizzato per la compilazione Java.

Più piattaforme e più linguaggi

La vera forza di Mono è però la libertà che offre, sia in termini di linguaggi che di architetture. Contrariamente a quanto avviene per la piattaforma .net di Microsoft, Mono supporta Windows, Linux, Mac OS X e differenti architetture hardware tra cui x86, PowerPC e SPARC. Inoltre, le librerie Mono (quali ad esempio gtk#) sono disponibili per tutte queste architetture, e permettono una reale programmazione multi-piattaforma.

Il runtime comune di Mono (ed il meccanismo di traduzione just in time) permette anche di svincolare il programmatore dal linguaggio. Si può sviluppare pressoché in qualunque linguaggio, da C# a VB, da Java a Python, Fortran, Lisp e Cobol. I linguaggi supportati sono veramente moltissimi (si veda ad esempio http://www.dotnetpowered.com/languages.aspx).

Alcuni strumenti

Mono contiene un discreto numero di strumenti a riga comando che permettono la compilazione e l'esecuzione di codice gestito, oltre che facilitare l'apprendimento del linguaggio C#.

mcs

mcs è il compilatore C# di mono. Il comando permette di compilare il codice, di includere risorse e collegare librerie di funzioni. Il risultato della compilazione è tipicamente un Assembly (una dll o un exe).

mono

mono è il comando che permette di eseguire un programma all'interno della macchina virtuale. mono utilizza il Jitter per tradurre il codice IL in codice nativo ed eseguirlo. Di seguito viene illustrato il risultato di mono --version, per il comando mono utilizzato di seguito per alcuni piccoli esempi.

$ mono --version
Mono JIT compiler version 1.9.1 (tarball)
Copyright (C) 2002-2007 Novell, Inc and Contributors. www.mono-project.com
        TLS:           __thread
        GC:            Included Boehm (with typed GC)
        SIGSEGV:       altstack
        Notifications: epoll
        Architecture:  x86
        Disabled:      none

monodoc

Si tratta del visualizzatore di documentazione incluso con il progetto Mono. Permette di sfogliare la documentazione inclusa con le librerie ufficiali del progetto e di studiare i fondamenti del linguaggio C#. Anche gli assembly installati da terze parti possono includere documentazione visibile da tale programma.

[monodoc]

Figura 1: monodoc

monop2

Nel caso in cui non sia facile trovare documentazione sui metodi o la definizione di una struttura o di una classe, o qualora si sia interessati unicamente all'elenco di metodi e proprietà, può essere d'aiuto il comando monop2. Di seguito un esempio.

$ monop2 System.Int32
[Serializable]
public struct Int32 : IComparable, IComparable, IConvertible, IEquatable, IFormattable {
        
        public static int Parse (string s);
        public static int Parse (string s, IFormatProvider fp);
        public static int Parse (string s, System.Globalization.NumberStyles style);
        public static int Parse (string s, System.Globalization.NumberStyles style, IFormatProvider fp);
        public static bool TryParse (string s, out int result);
        public static bool TryParse (string s, System.Globalization.NumberStyles style, IFormatProvider provider, out int result);
        public int CompareTo (int value);
        public int CompareTo (object v);
        public bool Equals (int value);
        public override bool Equals (object o);
        protected virtual void Finalize ();
        public override int GetHashCode ();
        public Type GetType ();
        public TypeCode GetTypeCode ();
        protected object MemberwiseClone ();
        bool System.IConvertible.ToBoolean (IFormatProvider provider);
        byte System.IConvertible.ToByte (IFormatProvider provider);
        char System.IConvertible.ToChar (IFormatProvider provider);
        DateTime System.IConvertible.ToDateTime (IFormatProvider provider);
        decimal System.IConvertible.ToDecimal (IFormatProvider provider);
        double System.IConvertible.ToDouble (IFormatProvider provider);
        short System.IConvertible.ToInt16 (IFormatProvider provider);
        int System.IConvertible.ToInt32 (IFormatProvider provider);
        long System.IConvertible.ToInt64 (IFormatProvider provider);
        sbyte System.IConvertible.ToSByte (IFormatProvider provider);
        float System.IConvertible.ToSingle (IFormatProvider provider);
        object System.IConvertible.ToType (Type conversionType, IFormatProvider provider);
        ushort System.IConvertible.ToUInt16 (IFormatProvider provider);
        uint System.IConvertible.ToUInt32 (IFormatProvider provider);
        ulong System.IConvertible.ToUInt64 (IFormatProvider provider);
        public override string ToString ();
        public string ToString (IFormatProvider provider);
        public string ToString (string format);
        public string ToString (string format, IFormatProvider fp);
        
        public const int MaxValue = 2147483647;
        public const int MinValue = -2147483648;
}

monodevelop

È un'IDE avanzata per la programmazione con Mono. Sviluppata in gtk#, deriva dal noto SharpDevelop. monodevelop include parecchie funzionalità di un ambiente di sviluppo integrato avanzato: documentazione integrata, autocompletamento del codice, intellisense, supporto alla compilazione, gestione dei riferimenti (collegamenti ad assembly esterni e non solo).

[monodevelop nuovo progetto]

Figura 2: monodevelop nuovo progetto

[monodevelop intellisense]

Figura 3: monodevelop IDE con intellisense

Utilizziamo gli strumenti offerti sino ad ora per compilare una semplice applicazione console. Il classico esempio iniziale per qualunque linguaggio di programmazione è ovviamente HelloWorld. Il programma non farà altro che stampare a terminale un saluto, eventualmente accettando un parametro con il nome dell'utente da salutare. Per farlo, creare un file HelloYou.cs e incollarvi il codice seguente:

using System;

public class EntryClass
{
        public static void Main(string[] args)
        {
                if(args.Length != 1)
                {
                        Console.WriteLine("Hello World!!");
                        return;
                }
                Console.WriteLine(String.Format("Hello {0}!!", args[0].ToUpper()));
        }
}

Quindi lanciare i comandi per la compilazione e l'esecuzione del programma. Il compilatore utilizzato in questo caso è gmcs, il compilatore della versione 2.0 (mcs è quello per la versione 1.0).

$ gmcs HelloYou.cs
$ mono HelloYou.exe
Hello World!!
$ mono HelloYou.exe gabriele
Hello GABRIELE!!

Si può anche complicare il programma e dotarlo di una banalissima interfaccia grafica. In mono è stato aggiunto il supporto alle librerie System.Windows.Forms, che permettono l'uso di controlli e componenti in stile Windows. Si può ad esempio pensare di creare una piccola finestra, con una casella di testo ed un pulsante, che visualizzi un messaggio di saluto una volta inserito il nome e premuto il tasto.

using System;
using System.Windows.Forms;

public class MainClass
{
        public static void Main()
        {
             Application.Run(new HelloForm());  
        }
}

public class HelloForm : Form
{       
        private System.Windows.Forms.Label label1;
        private System.Windows.Forms.TextBox tbNome;
        private System.Windows.Forms.Button btOk;

        public HelloForm()
        {
            InitializeForm();
        }

        private void btOk_Click(object sender, EventArgs e)
        {
            MessageBox.Show("Hello " + tbNome.Text);
        }

        private void InitializeForm()
        {
            this.label1 = new System.Windows.Forms.Label();
            this.tbNome = new System.Windows.Forms.TextBox();
            this.btOk = new System.Windows.Forms.Button();
            this.SuspendLayout();
           
            this.label1.AutoSize = true;
            this.label1.Location = new System.Drawing.Point(11, 9);
            this.label1.Name = "label1";
            this.label1.Size = new System.Drawing.Size(99, 13);
            this.label1.TabIndex = 0;
            this.label1.Text = "Inserisci il tuo nome";
           
            this.tbNome.Location = new System.Drawing.Point(12, 36);
            this.tbNome.Name = "tbNome";
            this.tbNome.Size = new System.Drawing.Size(259, 20);
            this.tbNome.TabIndex = 1;
            
            this.btOk.Location = new System.Drawing.Point(14, 75);
            this.btOk.Name = "btOk";
            this.btOk.Size = new System.Drawing.Size(75, 23);
            this.btOk.TabIndex = 2;
            this.btOk.Text = "Ok";
            this.btOk.Click += new System.EventHandler(this.btOk_Click);

            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(284, 105);
            this.Controls.Add(this.btOk);
            this.Controls.Add(this.tbNome);
            this.Controls.Add(this.label1);
            this.Name = "HelloForm";
            this.Text = "HelloYou";
            this.ResumeLayout(false);
            this.PerformLayout();
        }
}

Si osservi come venga facilmente aggiunto l'evento di pressione del tasto: è sufficiente utilizzare l'operatore += per aggiungere un delegato che si occupi della gestione dell'evento OnClick del pulsante. Per compilare il programma è necessario includere l'opzione -pkg:dotnet affinché venga gestito correttamente il riferimento alle librerie windows forms del framework 2.0.

$ gmcs HelloWin.cs -pkg:dotnet
$ mono HelloWin.exe

Di seguito una immagine del programma in esecuzione.

[hellowin]

Figura 4: hellowin

Infine, visto che precedentemente è stato citato gtk#, vediamo anche un piccolo esempio con un'interfaccia diversa. In questo caso nella finestra principale appare un solo pulsante, premuto il quale il saluto viene visualizzato sulla console. Di seguito viene riportato il codice del programma e un'immagine illustrativa del suo funzionamento.

using System;
using Gtk;

public class MainClass 
{
        public static void Main (string[  ] args)
        {
                Application.Init( );

                Window w = new Window ("Hello Gtk");
                Button b = new Button ("Ok");
        
                b.Clicked += new EventHandler (Button_Clicked);

                w.Add (b);
                w.SetDefaultSize (200, 100);
                w.ShowAll();

                Application.Run ( );
        }

        static void Button_Clicked (object o, EventArgs args)
        {
                System.Console.WriteLine ("Hello, World!");
        }
}

Si compila il programma, dando il riferimento alle librerie gtk#.

$ gmcs HelloGtk.cs -pkg:gtk-sharp-2.0
$ mono HelloGtk.exe 

Ed ecco il risultato.

[hellogtk]

Figura 5: hellogtk

Conclusioni

Con la versione 2.0 Mono ha incluso il supporto a un notevole numero di librerie ed effettuato molti miglioramenti rispetto alla versione precedente. Si comincia dalle API con compatibilità Microsoft, come ADO.NET 2.0 (accesso ai database) e ASP.NET 2.0 (sviluppo di pagine web e webservice), Windows.Forms 2.0 per la creazione di applicazioni desktop, e si prosegue con una versione rivista di System.Core che fornisce il supporto per Language Integrated Query (LINQ).

A seguire, le API Mono, che vanno da GTK# 2.12 per la creazione di applicazioni desktop su Linux, Windows e Mac OS X, a Mono.Cecil per la manipolazione di file in formato nativo ECMA CLI, a Mono.Cairo e l'API grafica 2D per il rendering in svariate forme, compresi i formati postscript e PDF, il supporto SQLite e Mono.Posix, una libreria per l'accesso a funzionalità specifiche di Linux e UNIX dall'applicazione managed.

Si cominciano a trovare in rete parecchi progetti che fanno uso della piattaforma di programmazione Mono per lo sviluppo: dal motore di SecondLife, completamente riscritto, a progetti quali Banshee Media Player, F-Spot Photo Manager, o TomBoy Notes.

Mono è un progetto maturo, e può essere d'aiuto anche in progetti complessi. L'uso di webservice e di tecniche di programmazione distribuita permettono anche di creare applicazioni web o smartclient di alto impatto e usabilità. Un progetto da seguire con interesse.

Buona programmazione a tutti!

Riferimenti bibliografici

[1] Mono homepage:
http://www.mono-project.com/



L'autore

Gabriele Pranovi è laureato in Ing. Elettronica all'Università di Brescia. Si occupa prevalentemente di progettazione e sviluppo di applicazioni Web in ambiente Microsoft .Net, e di gestione di database SqlServer. Programma in ASP.NET e C#. Ha lavorato come sistemista Windows e Red Hat, e da sempre è patito di Linux e di tutto ciò che fa parte del mondo Open.




Sinistra <- Duplicazione di un sistema - Indice Generale - Copertina - Installazione e configurazione di un server Linux -> Destra