Nota del autor

Si la entrada que estás leyendo carece de imágenes, no se ve el vídeo que teóricamente lleva incrustado o el código fuente mostrado aparece sin formato, podéis conocer los motivos aquí. Poco a poco iré restableciendo la normalidad en el blog.
Este blog es un archivo de los artículos situados previamente en Lobosoft.es y ha dejado de ser actualizado. Las nuevas entradas pueden encontrarse en www.lobosoft.es. Un saludo,
Lobosoft.

martes, 29 de abril de 2008

Generación de código con DSL Tools

Una de las posibilidades más interesantes de DSL Tools para Visual Studio es la generación de artefactos y código a partir del elementos pertenecientes al modelo de dominio que definamos para nuestro DSL. En el ejemplo de hoy usaremos el proyecto más básico de cuantos ofrece Visual Studio DSL Tools para obtener un generador de código básico que permitirá, definir un "lenguaje de programación visual" para nuestros usuarios. Obviamente, el alcance de la programación será algo limitado, máxime si tenemos en cuenta que se trata de un mero ejemplo de generación de código, pero nos permitirá vislumbrar hasta qué punto es potente y flexible esta herramienta.


En primer lugar, entramos a Visual Studio y creamos un nuevo proyecto Domain-Specific Languaje Designer, dentro de las plantillas Extensibility. Daremos un nombre a la solución, por ejemplo, MyDSLGenerator, y al pulsar en OK aparecerá un asistente para definir algunos de los parámetros de nuestro DSL. Seleccionaremos la plantilla MinimalTemplate, la extensión que tendrán los archivos de nuestro lenguaje (.mydlsg, en este ejemplo), y otras características como el espacio de nombres raíz para los proyectos de la solución. Hecho esto, pulsaremos en Finalizar, y tendremos ante nosotros el diseñador del DSL. Lo primero que nos preguntará siempre (a menos que indiquemos que no deseamos ser advertidos de ello) es que va a procederse a regenerar todos los archivos de la solución a partir de los Text Templates (archivos .tt) de la misma. Aceptamos, y nos encontraremos con algo similar a lo siguiente:



dsl1.PNG


Aunque podemos personalizar todo el DSL desde el proyecto Dsl de la solución, optaremos en esta entrada introductoria por hacer los mínimos cambios posibles. En primer lugar, hemos renombrado el nombre de los elementos del diagrama (ExampleShape, ExampleConnector, etc.).



dsl2.PNG


Lo más importante aquí va a ser definir una nueva propiedad de dominio sobre la clase xxElement (en nuestro caso, ActivityElement), ya creada por la propia plantilla del DSL. A esta propiedad podremos darle un valor, posteriormente, para cada Shape correspondiente a la clase que dibujemos en nuestro diseñador, o lo que es lo mismo, para cada objeto instanciado de la clase. Introduciremos una actividad denominada "Activity", de tipo string.



dsl21.PNG


Dentro del DSL Explorer haremos lo propio con las opciones correspondientes al Editor (Editor->Toolbox Tabs-> ActivitiesDesigner->Tools), para que aparezcan también los nombres en el Visual Studio Hive, y en la aplicación DSL una vez que la instalemos en otro equipo.



dsl3.PNG


Volvemos a generar el código del proyecto, pulsando sobre el botón Transform All Templates, y ejecutamos (F5). Aparecerá el Visual Studio Hive.


Creamos un diagrama acorde con lo especificado en nuestro DSL. Por ahora, lo único que hará es asignar una serie de propiedades a los Shapes (los rectángulos correspondientes a nuestras actividades). Estas propiedades son las que definimos anteriormente en el diseñador del DSL. Por un lado, la propiedad Name, que ya venía definida con la propia clase, y la propiedad Activity, que incluimos en ese momento.



dsl5.PNG


Para cada Shape, damos valor a las propiedades Name y Activity.



dsl6.PNG


Ahora vamos a preparar nuestro generador de código. Se tratará de un TextTemplate, de modo que añadimos un nuevo elemento al proyecto, de tipo fichero de texto, con el nombre LibraryCode.tt, y que va a permitir la generación de código a partir de los elementos existentes en nuestros diagramas. Más adelante nos quedará ver cómo llevar a cabo esta acción automáticamente cada vez que añadamos un elemento de nuestro lenguaje (archivo con extensión .mydlsg, que es la que definimos con este fin). De momento, lo generamos a mano, y le damos contenido.








using System;
using System.Collections.Generic;
using System.Text;
using LOBOSOFT.MyDSLGenerator;

namespace LOBOSOFT.Activity
{


///
/// The MainClass is the enter point for the functionality of this assembly
///
public class MainClass
{
public void MainMethod()
{
<# /* Calls to the private classes */
foreach(ActivityElement activity in this.ActivitiesModel.Elements){ #>
// Sequential caller
Class oClass = new Class();
oClass.m();


}
}

<# /* Creating classes for the Diagram Activities */
foreach(ActivityElement activity in this.ActivitiesModel.Elements)
{
#>
///
/// The Class gives functionality for managed class (test case)
///
public class Class
{
public void m()
{
o = new ();
o.MainMethod();
}
}
<#
}
#>

}

A grandes rasgos, este código se encarga de recorrer los elementos de nuestro diagrama, generando código según los valores que hemos definido para las propiedades. En primer lugar, se encuentran una serie de directivas.


<#@ template language="C#v3.5"..., por ejemplo, indica el lenguaje usado para la plantilla, ya que después de generar el código, será validado sintácticamente según las reglas del lenguaje, y compilado en una DLL cuando compilemos nuestro proyecto. El v3.5 es opcional, y sería necesario para aplicaciones que usen C# del .NET Framework 3.5 (como por ejemplo, que hagan uso de LINQ).
indica que haremos uso del archivo .mydslsg llamado Sample1. Por tanto, cada TextTemplate (.tt) irá vinculado inicialmente a un .mydslg, aunque veremos más adelante que esto podrá automatizarse.

El resto del template "escribe" el código en C# que necesitamos. Si pulsamos con el botón derecho del ratón sobre el archivo y seleccionamos la opción Run Custom Tool, o bien pulsamos sobre el botón Transform All Templates se generará el código C# asociado. En nuestro caso, el código correspondiente es el siguiente:


[csharp]
using System;
using System.Collections.Generic;
using System.Text;
using LOBOSOFT.ManagedDLLEncapsulation;

namespace LOBOSOFT.Activity
{

///
/// The MainClass is the enter point for the functionality of this assembly
///
public class MainClass
{
public void MainMethod()
{
// Sequential caller
pruebaClass opruebaClass = new pruebaClass();
opruebaClass.mprueba();

}
}

///
/// The pruebaClass gives functionality for prueba managed class (test case)
///
public class pruebaClass
{
public void mprueba()
{
prueba oprueba = new prueba();
oprueba.MainMethod();
}
}

}
[/csharp]

El código será generado e incluso compilado si hemos incluido en las referencias del proyecto las DLLs que estamos usando.

Nos quedará por ver cómo automatizar varios de estos procesos, y cómo realizar el despliegue en otro ordenador de este DSL gráfico, pero eso será en una próxima entrega.

lunes, 28 de abril de 2008

Open Proj, la alternativa libre a Microsoft Project

A la hora de planificar un proyecto de desarrollo software que implique el trabajo de varios desarrolladores y diversas tareas a acometer, la herramienta idónea para ello era Microsoft Project. Sin embargo, y aunque el potencial de la herramienta es muy alto, posiblemente como ocurre con tantas otras, no llegamos a aprovechar ni el 50% de sus posibilidades en el día a día, lo que no justifica el importante gasto en licencias que supone adquirir una o más copias de la herramienta. Además, nos encontramos con una aplicación propietaria, de código cerrado, de la que no es posible saber qué hace entre bambalinas, ni personalizarla en modo alguno. Por si esto fuera poco, sólo funciona en sistemas Windows. Ante esto, si la magnitud de los proyectos que vamos a llevar a cabo no justifica la adquisición de una o más licencias de Microsoft Project, no deseamos usar software privativo o, simplemente, queremos buscar una alternativa a la aplicación de Microsoft, tenemos algunas opciones interesantes dentro del mundo del software libre.


openproj-big-small.jpg


Una de las más interesantes es Open Proj, una aplicación open source que puede utilizarse en Linux, Unix, Mac o Windows, y que además accepta ficheros en el formato Project de Microsoft. Aunque no ofrece el 100% de la funcionalidad de su hermano privativo, lo cierto es que ese 40% real que usamos del mismo viene soportado con creces en esta aplicación multiplataforma. La probé hace algún tiempo, y ahora que la estoy usando por propia iniciativa en proyectos profesionales he de admitir que no tiene nada que envidiar a la aplicación de Microsoft. Una interfaz gráfica de similares características (eso sí, algo menos fluida, debido a que usa JRE para su ejecución y los WinForms suelen ser más eficientes en entornos Windows), y similares opciones a la hora de gestionar nuestros proyectos. Recomendable, sin duda alguna.

Windows Server 2008 y PowerShell

 


powershell.jpg


El pasado 18 de abril asistí a una serie de charlas sobre los nuevos productos de Microsoft: Windows Server 2008, virtualización con Hyper-V, SQL Server 2008, IIS 7.0, Visual Studio 2008 y Silverlight 2.0. De todas ellas, una de las que me llamaron más poderosamente la atención fue la referentes a virtualización, ya que Hyper-V es un producto bastante interesante para aquellas empresas, cada vez más, que trabajan con virtualización, aunque los requisitos de la misma son algo exigentes, sobre todo respecto al hardware, ya que requieren de determinadas familias de procesadores que tengan soporte para la virtualización. La otra que me interesó (aunque dedicado a la programación desde hace unos cuantos añitos, el ser de Sistemas sigue tirando), es referente a Windows Server 2008 y un par de características de este sistema operativo para servidores. Una, la inclusión de un modo Windows Server Core, que no dispone de interfaz gráfica, solamente incluye línea de comandos, y que será idónea para servidores con los que no haya que interactuar habitualmente, o estén disponibles de forma remota. También, obvia decirlo, será una instalación ideal para equipos potentes, pero en los que no deseemos consumir recursos innecesarios en la interfaz gráfica. La forma de administrar estos servidores, al igual que cualquier otro Windows Server 2008 que se precie, será a través de la línea de comandos, con PowerShell, que es la otra novedad a que me refería, y la más interesante de todas. PowerShell es un entorno de trabajo en la línea de comandos que posibilitará a los administradores de sistemas exprimir al máximo las posibilidades de Windows Server. En mi caso, que trabajé hace unos años en la administración de servidores con Windows Server 2003 (particularmente creando entornos de seguridad y trabajo remoto mediante Active Directory e ISA Server), las herramientas de configuración del servidor se me quedaban cortas, y esto es algo que a cualquier administrador de sistemas Windows le habrá ocurrido a poco que haya intentado sacar partido a las posibilidades del sistema operativo. Esta tortura llega a su fin con PowerShell, ya que no sólo muchas de las opciones del Server estarán disponibles con un mayor potencial a través de su interfaz, sino que no serán accesibles de ningún otro modo.


 


ps.jpg


PowerShell permite además el trabajo conjunto de administradores y programadores, ya que su núcleo está basado en .NET Framework (es, por tanto, un Shell hasta cierto punto orientado a objetos), y Microsoft lo incorpora en Windows Vista y todas las versiones de Windows Server 2008. Sin embargo, para aquellos que deseen probarlo con Windows XP, es posible gracias a la instalación de un paquete que proporciona Microsoft, y que servirá para ir practicando antes de enfrentarnos a un Server 2008 en producción.


P.S.: Por cierto, quién lo diría hace unos años. Linux cada vez tiende más a sacar distribuciones para PCs de escritorio y usuarios finales, y Microsoft lanza un S.O. servidor, en modo consola y con un shell que nada tiene que envidiar a Korn o Bash o Bourne shell...

viernes, 25 de abril de 2008

Hacienda reclama a la SGAE sus deudas

Ya iba tocando poder leer una noticia como ésta. El fisco reclama a la SGAE unos 6 millones de euros por intereses de demora. Como ya dijo Stallman en una conferencia que dió en Gijón hace unos años, la SGAE "es muy mala, no merece existir y debe ser eliminada", añadiendo después que "la SGAE intenta aplacar la libertad de expresión con demandas para cerrar los sitios web que la critican y pretende eliminar el software capaz de compartir música, algo a lo que todo debemos
tener derecho". Encima, son mafi... esto... morosos. A ver si tiran de la manta de una vez. Y es que Hacienda somos todos ;).


Pulse sobre la imagen para ampliar.

miércoles, 23 de abril de 2008

Error en la web

¡No puedor, no puedor!, que diría el inefable Chiquito de la Calzada.


En la noche del 23 al 24 de abril (este San Jorge y su dragón...), la versión de Wordpress en el que se basa Lobosoft actualmente cayó por la tremenda carga en plugins que soportaba. Como me suele comentar mi amigo Fernando, de Alblogera, esto no es un blog, parece un portal web de tan rococó que resulta.


A los lectores que recibieron un error similar al siguiente:

Fatal error: Allowed memory size of 8388608 bytes exhausted (tried to allocate 77824 bytes) in /home/lobosxxx/xxxxxxxxxxxxx/wp-admin/includes/xxxxxxx.php on line 460



les debemos una disculpa. De momento, y ante la imposibilidad de solucionar el error del script (se trata de un problema de eficiencia con PHP 4 -aunque la cuestión es que en mi servidor se ejecuta PHP5-, la versión de Wordpress que uso, y posiblemente por una programación poco óptima de alguno de los plugins), he desactivado todos. El problema se da porque la base de datos ha crecido demasiado y en algún punto se intentan cargar en memoria demasiados datos, lo que provoca el error. Lo próximo va a ser, en estos días, una actualización de Wordpress y una criba de los plugins que mantengo. En cualquier caso, y por si alguien recibiese un error similar, los pasos a probar serían:




  1. Si tenemos acceso al servidor, cambiar en el fichero /etc/php5/apache2/php.ini la variable memory_limit = 8M por 16M o los que consideremos necesarios.

  2. Si no es así, incluir en el script que da el problema (justo al inicio), la línea ini_set(”memory_limit”,”16M”);


Después de esto, hemos lucido este "lindo diseño minimalista":

errorweb.PNG


Al menos hasta que mi proveedor de hosting ha aumentado la memoria dedicada a los procesos PHP. Una vez más, pedir disculpas. En breve toda la funcionalidad del sitio web estará restablecida.

lunes, 21 de abril de 2008

Uso dinámico de código no manejado desde .NET

El último día estuvimos viendo cómo usar las funciones de librerías creadas en C desde C#, realizando una importación de la misma en el momento de la compilación. Para ello, era necesario adornar con el atributo DllImport la función que deseáramos usar, y el CLR nos permitiría acceder a la misma. Sin embargo, podría darse el caso de necesitar enlazar con la librería en tiempo de ejecución, por ejemplo, porque fuese un elemento de terceros, o que proporcionase el propio usuario en un momento dado para usarla dentro de nuestra aplicación .NET, por ejemplo, dándonos un codificador o una funcionalidad específica. En ese caso, el proceso se complica un poco (pero no mucho), como veremos a continuación.


Lo primero que tenemos que hacer es pensar cómo estructura la memoria el CLR, y de qué manera se produce la ejecución de una aplicación .NET. Todo el código .NET es código manejado, y como tal se ejecuta sobre un framework, en una capa superior a la del sistema operativo, en una zona de memoria que podríamos denominar "segura". El código no manejado tiene acceso a recursos del propio sistema operativo, lo que lo hace más inseguro, pero a la vez más rápido y eficaz en algunas tareas. Cuando el CLR ejecuta una de nuestras aplicaciones .NET, éstas no tienen acceso a los recursos del sistema de una forma directa, sino a través del propio Framework, lo que evita accesos indebidos a recursos del sistema, así como un mayor control en caso de error. Sin embargo, esto también dificulta el acceso a las funciones que deseamos usar desde las .DLLs (hay que tener en cuenta que las DLLs de .NET no son iguales a las que obtenemos con un compilador de C o C++ "al uso"). Por ello, si queremos usar de forma dinámica de éstas, deberemos recurrir a algún pequeño truco. El primero de ellos, y el más evidente, sería usar código en C++ para acceder a la función de la DLL que deseásemos, y lanzarlo, actuando en cierto modo como un "proxy" entre el código manejado y el no manejado. Sin embargo, esta solución, si bien no es mala, implica un problema y es que para cada función requeriríamos una función proxy en C++. Otra opción más óptima es la de usar algo de lenguaje ensamblador para codificar la llamada a la función, y utilizar librerías de Win32 para ejecutar la llamada.


capas.PNG


Una posible implementación del código en ensamblador sería la siguiente:





; -------------------------------------------------------------
;
; InvokeFuncAsm - Invokes a function through a function pointer passed as
; the first argument. All other parameters are forwarded on, plus the return
; value of the function invoked is returned.
;
; Copyright (c) Richard Birkby, ThunderMain ltd, November 2001
;
; -------------------------------------------------------------

.386
.model flat

option prologue:none
option epilogue:none
option dotname

.code
align DWORD
DllMain proc stdcall public, instance:DWORD, reason:DWORD, reserved:DWORD
mov eax, 1 ; success
ret 12
DllMain endp

align DWORD
InvokeFunc proc stdcall public, funcptr:DWORD

pop ecx ; save return address
pop edx ; Get function pointer
push ecx ; Restore return address
jmp edx ; Transfer control to the function pointer
InvokeFunc endp

end


El código es de Richard Birkby, ya que tengo el ensamblador suficientemente oxidado como para no lanzarme a programar algo así, aunque no sea excesivamente complejo. Básicamente, el código recibe el un puntero a la función a invocar así como los parámetros que recibirá. La carga de la DLL que queremos usar se hará a través de la función LoadLibrary de Kernel32, y su dirección dentro del espacio de ejecución de la aplicación la podemos obtener con GetProcAddress, también de Kernel32. Se ejecuta la función mediante el código en ensamblador, que a su término retorna el valor con una instrucción jmp, que devuelve además el control a la aplicación que la llamó. Al finalizar, liberamos los recursos con FreeLibrary. El código completo puede verse a continuación.



[csharp]
///


/// Usa la librería mediante una importación dinámica, en tiempo de ejecución
///

class UsoDinamico
{
[DllImport("kernel32.dll")]
static extern IntPtr LoadLibrary(string csFileName);

[DllImport("kernel32.dll")]
static extern IntPtr GetProcAddress(IntPtr IntPtr_Module, string
csProcName);

[DllImport("kernel32.dll")]
static extern bool FreeLibrary(IntPtr IntPtr_Module);

[DllImport("Invoke", CharSet = CharSet.Unicode)]
static extern int InvokeFunc(IntPtr funcptr, int operando1,
int operando2);

///
/// Calcula la operación Suma sobre todos los enteros introducidos en los parámetros
/// de la aplicación de consola
///

///
public static void Calcular(string[] args)
{
IntPtr DllACargar = LoadLibrary("c_math_lib.dll");
IntPtr PunteroAFuncion = GetProcAddress(DllACargar, "Sum");
int resultado, operando;

resultado = 0;

for (int i = 0; i < args.Length; i++)
{
int.TryParse(args[i], out operando);
resultado = InvokeFunc(PunteroAFuncion, resultado, operando);
}

Console.WriteLine("El resultado de la operación es " + resultado);

FreeLibrary(DllACargar);
}
}
[/csharp]

Como vemos, es bastante sencillo usar una librería dinámicamente, tanto con una importación implícita, en tiempo de compilación, como explícita durante la ejecución del programa. Nos quedará ver cómo saber qué funciones ofrece, por ejemplo, una DLL, sin necesidad de conocer sus nombres desde un principio, pero esto será tema para otra entrada.

sábado, 19 de abril de 2008

Usando código no manejado desde .NET (con C#)

Una de las situaciones con las que me he encontrado habitualmente en el trabajo, particularmente cuando lo hacía con autómatas y, especialmente, con entornos y lenguajes de programación diversos, era la necesidad de comunicar los diversos procesos, que podían ser aplicaciones completas (y complejas), con una funcionalidad específica e independiente, pero que trabajando en conjunto permitían obtener más beneficios para el usuario. Esto es particularmente cierto, y muy usado, en entornos UNIX, donde cientos de pequeñas (a la par que potentes) aplicaciones interactúan entre sí para permitir incluso la programación de scripts mediante los diversos lenguajes de shell que incorporan.

Sin embargo, hay ocasiones en las que las aplicaciones no han sido pensadas para facilitar este uso, y sus salidas y entradas pueden ser de lo más diversas: stdin/stdout, ficheros de texto o binarios, grabación en bases de datos, uso de sockets, etc. En estos casos, o bien tenemos acceso al código fuente y podemos establecer algún vínculo de comunicación específico, o debemos ingeniárnoslas como mejor podamos para comunicar estos procesos. Si es posible.

Recientemente me encontré en la tesitura de usar aplicaciones desarrolladas en diversos lenguajes (C, C++…) desde .NET Framework. Aunque podría tratarse de ejecutables como tales, lo ideal en este caso, de cara a una futura integración con .NET y ante la imposibilidad de reciclar a todo el personal, el equipo material, etc., lo ideal era reconvertir estas aplicaciones en otras "huecas" que usasen la funcionalidad actual a través de su compilación como librerías DLL, e implementar las futuras que se desarrollasen también mediante DLLs. Sin embargo, aún me encontraba con un pequeño problema. ¿Cómo usar dichas librerías desde .NET? Por un lado, habría que tener en cuenta que las librerías .DLL de .NET Framework no son iguales a las .DLL "de toda la vida", sino que contienen código para ser ejecutado por el CLR. Sin embargo, las .DLLs de C, por ejemplo, contienen código no manejado, que es ejecutado directamente por el sistema operativo, y no por una máquina virtual, como ocurre en .NET o Java. Esto es posible mediante el uso de las librerías que aporta el propio sistema operativo, como veremos a continuación.

Usando una .DLL creada en C, desde C#

El modo más sencillo de usar una librería de C desde .NET es, sin duda, importarla en la compilación de nuestro código. Esto lo conseguimos mediante el atributo [DllImport()], en el que indicaremos la DLL a cargar. Posteriormente declararemos las funciones que deseamos usar de la misma, y listo. Por ejemplo, imaginemos el siguiente código C:int

[c]Sum(int a, int b)
{
return a+b;
}[/c]

Una función que toma dos números enteros, y devuelve el resultado. Para probarlo, creamos un proyecto vacío de Visual C++, de tipo librería DLL, y creamos un archivo con dicha función. Añadimos un fichero de definición del módulo (.def), y le agregamos las líneas:

LIBRARY "c_math_lib"
EXPORTS
Sum


Mediante las mismas, declaramos el nombre de la librería así como las funciones que pone a disposición de sus usuarios (en cierto modo, las que son públicas). Compilamos en modo Release para obtener la librería.

Creamos ahora otra solución (aunque el anterior podría ser un proyecto dentro de la misma) de consola en Visual C#, e incluimos la DLL generada anteriormente.

[csharp]namespace Lobosoft.UsoDLLNoManejadas
{
///
/// Entrada al programa.
/// Usa la librería mediante una importación en tiempo de compilación
///

class Program
{
static void Main(string[] args)
{
[DllImport("c_math_lib.dll")]
static extern int Sum(int a, int b);

int resultado, operando;
resultado = 0;

for (int i = 0; i < args.Length; i++)
{
int.TryParse(args[i], out operando);
resultado = Sum(resultado, operando);
}
Console.WriteLine("El resultado de la operación es " + resultado);
}
}[/csharp]

El atributo DllImport indica a Visual Studio que importe la librería en tiempo de compilación, de modo que reservará la memoria y permitirá usar la función Sum declarada como externa. El programa simplemente recuperará los valores que se pasen como argumentos en la ejecución del programa, irá sumándolos, y devolverá el resultado por pantalla.

suma1.PNG



Puede verse que es bastante simple hacer uso de código no manejado en .NET, aunque surgen otras dudas, como, por ejemplo, cómo cargar dinámicamente una DLL, en tiempo de ejecución o cómo conocer qué funciones pone a nuestra disposición. Esto lo veremos en sucesivos artículos.