G A C E T A   D E   L I N U X
...haciendo a Linux un poco más divertido!
Bits de Programación: Conociendo C# y Mono
Por Ariel Ortiz Ramirez
Traducción al español por Daniel Guerrero
el día 1 de Enero 2003, para La Gaceta de Linux

 

C# (pronunciado C-gato, o en inglés C-sharp) es un nuevo lenguaje de programación orientado a objetos diseñado para tomar ventaja del framework de desarrollo .NET de Microsoft. Tiene muchas similaridades con otros lenguajes orientados a objeto populares como C++ y Java, pero aún ofrece algunas nuevas características.

Linux ofrece la oportunidad de desarrollar aplicaciones C# gracias al proyecto llamado Mono. Mono es una implementación open source de la plataforma .NET. En las siguientes secciones, describiré los elementos principales de la implementación actual del sistema Mono.

El Proyecto Mono

Actualmente, Mono implementa dos estándares: el lenguaje de programación C# (Estándar ECMA-334) y la Infraestructura de Lenguaje Común (Common Languaje Infraestructure, Estándar ECMA-335). Ambas especificaciones fueron desarrolladas por Microsoft y enviadas a ECMA (un consorcio de fabricantes formalmente conocido como la Asociación Europea de Fabricantes de Computadoras) en Octubre del 2000. Estos fueron formalmente aprobados en Diciembre de 2001, y posiblemente se convertirán en estándares ISO (gracias al acuerdo de "seguimiento-rápido" que ISO tiene con ECMA) poco antes del final del siguiente año.

El proyecto Mono es patrocinado por Ximian, la misma compañía que nos brindó el ambiente gráfico de escritorio GNOME. El hacker mexicano y CTO de Ximian, Miguel de Icaza actualmente dirige el desarrollo de este proyecto. En mi opinión, la gente involucrada con el desarrollo de Mono ha hecho un trabajo notable en poco tiempo. A propósito, la palabra "Mono" viene del español. A los tipos de Ximian realmente les gustan los monos.

¡Hola Mundo de Mono!

Vamos a realizar un ejemplo simple de programación para poder entender cómo C# y los diferentes componentes de mono interactúan. Para ver esto en acción, asegúrate que tengas una instalación de Mono trabajando (ver la sección de recursos para información acerca de descargar e instalar Mono).

La siguiente imagen resume el proceso que seguiremos para poder compilar y ejecutar nuestro programa C#:

Compilando y Ejecutando Programas C#.

Primero, crearemos el código fuente de un programa simple en C# (el clásico "¡Hola mundo!" no puede perderse). Escribe el siguiente programa usando tu editor de textos favoritos y guarda el archivo como hello.cs:

class Hello {
    public static void Main() {
        System.Console.WriteLine("!Hola Mundo de Mono!");
    }
}

Esta clase está compuesta de una clase llamada Hello que contiene un método llamado Main. Este método establece el punto de la entrada del programa, de la misma forma que la función main es el inicio de un programa C/C++. En este ejemplo, el método Main imprime a la salida estándar el mensaje "!Hola Mundo de Mono!"

Podemos compilar el programa usando el compilador Mono de C#, llamado mcs. En el prompt de la consola, escribe:

mcs hello.cs

Ahora debemos tener un archivo llamado hello.exe en el directorio actual. Pero no te confundas con la extensión .exe en el nombre del archivo. No es un archivo ejecutable de Windows, al menos no de la manera en que estamos acostumbrados. Contrario a lo que pasa cuando compilamos un programa en lenguajes como C o C++, el compilador C# no genera un archivo objeto específico a una máquina (por ejemplo un archivo objeto ELF x86 de Linux), pero en su lugar genera un binario especial llamado un ensamblado que está constituido por Metadatos e instrucciones de lenguaje intermedio (IL). Estos dos representan una traducción agnóstica de plataforma del programa en código fuente. Esto significa, claro, que cuando ejecutemos el programa contenido en el ensamblado, es un código en lenguaje intermedio que tiene que ser traducido al código nativo de la computadora donde el programa será ejecutado. Esta última fase de traducción es realizada por una máquina virtual, cuyo comportamiento es definido por la especificación de la Infraestructura del Lenguaje Común (CLI). CLI define un ambiente de ejecución orientado a objetos que soporta una librería de clase base, carga dinámica de clase y ligado, ejecución múltiple de hilos, compilación justo-en-tiempo, y manejo automático de memoria. La implementación de Microsoft para la especificación CLI es usualmente referida como Ejecución de Lenguaje Común (CLR). Decimos que CLR es un conjunto mayor al de CLI debido a que CLR contiene algunas extensiones que no son parte de CLI.

Para ejecutar nuestro ensamblado, debemos invocar el programa llamado mono, que es la máquina virtual Mono. Escribe en el prompt de la consola lo siguiente:

mono hello.exe

La salida debe ser:

¡Hola Mundo de Mono!

Detrás de Cámaras

Veremos cómo examinar el contenido de nuestro ensamblado. El programa monodis (Desensamblador Mono) lee la información binaria de un ensamblado y produce una representación textual de su contenido. Escribe en el prompt de la consola:

monodis hello.exe

La salida del desensamblador debe ser algo como lo siguiente:

.assembly extern mscorlib
{
  .ver 0:0:0:0
}
.assembly 'hello'
{
  .hash algorithm 0x00008004
  .ver  0:0:0:0
}
  .class private auto ansi beforefieldinit Hello
        extends [mscorlib]System.Object
  {

    // línea 1 del método
    .method public hidebysig  specialname  rtspecialname
           instance default void .ctor()  cil managed
    {
        // El método inicia en RVA 0x20ec
        // Tamaño del código 7 (0x7)
        .maxstack 8
        IL_0000: ldarg.0
        IL_0001: call instance void valuetype [corlib]System.Object::.ctor()
        IL_0006: ret
    } // fin de la instancia del método por defecto void .ctor()

    // línea 2 del método 
    .method public static
           default void Main()  cil managed
    {
        // El método inicia en RVA 0x20f4
        .entrypoint
        // Tamaño del código 11 (0xb)
        .maxstack 8
        IL_0000: ldstr "¡Hola Mundo de Mono!"
        IL_0005: call void class [corlib]System.Console::WriteLine(string)
        IL_000a: ret
    } // fin del método por defecto void Main()

  } // fin del archivo Hello

La primera parte de la salida corresponde a los metadatos. Contiene información acerca de la versión actual del ensamblado, cualquier restricción opcional de seguridad, información local, y una lista de todos los ensamblajes externos referenciados que son requeridos para la ejecución apropiada. El resto de la salida representa el código IL. Podemos señalar dos puntos en este código: el constructor por defecto de la clase llamado .ctor, provisto automáticamente por el compilador, y nuestro método Main,. Como se describió anteriormente, cuando una máquina virtual se le solicita que ejecute este código, usa un compilador (JIT) justo-en-tiempo para traducir el IL en un código nativo de máquina del ambiente actual. El código nativo no es generado hasta que es necesitado (por eso el nombre justo-en-tiempo). Para nuestro ejemplo, lo siguiente es el código de máquina nativo x86 (en sintaxis de lenguaje ensamblador AT&T) que es generado para el método Main

push   %ebp
mov    %esp,%ebp
sub    $0x30,%esp
push   $0x80c9eb0
mov    0x805462c,%eax
push   %eax
cmpl   $0x0,(%eax)
mov    (%eax),%eax
call   *0x94(%eax)
add    $0x8,%esp
mov    0x805462c,%eax
push   %eax
cmpl   $0x0,(%eax)
mov    (%eax),%eax
call   *0xb4(%eax)
add    $0x4,%esp
leave
ret

Mono también viene con un intérprete llamado mint. Si usas este programa, las instrucciones IL son interpretadas en vez de ser compiladas a código nativo por JIT. De hecho, nuestro programa simple debe ser un poco más rápido cuando lo ejecutamos con mint debido a que el compilador JIT tomará algún tiempo en compilar el código de nuestro programa y almacenarlo en algún lugar de la memoria. Claro, ejecuciones subsecuentes del código nativo que ya está en memoria es definitivamente más rápido que una interpretación. Actualmente el compilador JIT está sólo disponible para máquinas x86. El intérprete Mono debe ser usado en cualquier máquina que no sea x86. Para ver el intérprete ejecutándose, escribe en el prompt de la consola:

mint hello.exe

Si estás familiarizado con Java, debes estar pensando que toda esta tecnología suena muy similar a la forma en que la plataforma Java trabaja. Y esto es en verdad así. La máquina virtual CLI es el factor clave para la independencia de plataformas. Esto significa que puedo escribir y compilar un programa en Linux usando Mono, y después ejecutarlo en una computadora con Windows con el framework .Net. No hay necesidad de reescribir o recompilar el código fuente. Pero en contraste con la máquina virtual de Java, que está firmemente acoplada al lenguaje de programación Java, la especificación CLI no sólo permite la independencia de plataforma, también permite la independencia de lenguaje. Windows tiene compiladores que son diseñados para CLR de varios lenguajes. Los más importantes son parte del ambiente de desarrollo Visual Studio .NET de Microsoft: Visual Basic .NET, JScript .NET, Managed C++ y C#. Otros lenguajes soportados por fabricantes terciarios, incluyen APL, COBOL, Eiffel, Forth, Fortran, Haskell, Mercury, Mondrian, Oberon, Pascal, Perl, Python, RPG, Scheme y SmallScript. El proyecto Mono sólo tiene un compilador C# por el momento, pero probablemente veremos en un futuro cercano que otros lenguajes sean soportados.

Otro elemento importante del CLI es el Sistema de Tipo Común (CTS). CTS describe totalmente todos los tipos de datos soportados por la máquina virtual, incluyendo cómo esos tipos de datos interactúan con otros y cómo son representados como metadatos dentro de los ensamblados. Es importante notar que no todos los lenguajes disponibles para el CLI soportan todos los tipos de datos en el CTS. Así que existe una Especificación de Lenguaje Común (CLS), que feine un subconjunto de tipos comunes que aseguran que los binarios ensamblados puedan ser usados por todos los lenguajes que soporta el CLI. Esto significa que si construimos una clase CLI que sólo expone características conforme a CLS, cualquier lenguaje compatible con CLI puede usarl. Puedes crear una clase en Eiffel, hacer una subclase en C# e instanciarla en un programa de Visual Basic .NET. Esto es una interoperabilidad real de lenguajes.

Algunas Ventajas

Usando una plataforma conforme a CLI, como Mono o el framework .NET, tiene algunas ventajas importantes:

C#, como lenguaje de programación, tiene algunas características importantes:

Discutiré esos y otros apartados de C# más a fondo en artículos posteriores

Recursos

http://www.go-mono.com/
La página oficial de Mono. Las instrucciones para descargar e instalar pueden ser encontradas aquí
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndotnet/html/deicazainterview.asp
Una entrevista muy interesante con Miguel de Icaza sobre el proyecto Mono y el uso de los estándares ECMA.
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cscon/html/vcoriCStartPage.asp
Información del lenguaje de programación C# en MSDN..
http://www.ecma.ch/ecma1/STAND/ecma-334.htm
El Estándar ECMA-334 de la especificación del lenguaje C#.
http://www.ecma.ch/ecma1/STAND/ecma-335.htm
El estándar ECMA-355 de la Infraestructura de Lenguaje Común.

Copyright © 2002, Ariel Ortiz Ramirez. Licencia de copiado http://www.linuxgazette.com/copying.html
Puiblicado en la Edición 84 de La Gaceta de Linux, Noviembre 2002