Sunday, February 28, 2010

Miniprueba con SWIG

Hoy hice una pequeña prueba con SWIG.
El ejemplo que aparece en SWIG: donde C y Python se dan la mano (está muuuy bien explicado) hizo que me picará la curiosidad.

SWIG es una herramienta que permite conectar programas escritos en C/C++ con diferentes lenguajes de alto nivel (lenguajes que soporta).
En este caso, lo probé con Python y C.

Este es el header de mi código en C:
#ifndef __DATOS_PERSONALES_H__
#define  __DATOS_PERSONALES_H__

#include 
#include 

/* Tipos */
typedef struct {
  char nombre[150];
  int  edad;
}DatosPersona;

/* Prototipos */
extern int edad_get(DatosPersona a);
extern char * nombre_get(DatosPersona a);
extern void nombre_set(DatosPersona *a, char * nombre);
extern void edad_set(DatosPersona *a, int edad);
extern void muestra(DatosPersona a);

#endif /* __DATOS_PERSONALES_H__ */

Y este es el código en si:
#include "datosPersonales.h"

int edad_get(DatosPersona a)
{
    return a.edad;
}

char * nombre_get(DatosPersona a)
{
   return a.nombre;
}

void nombre_set(DatosPersona *a, char * nombre)
{
   strcpy(a->nombre, nombre);
}

void edad_set(DatosPersona *a, int edad)
{
    a->edad = edad;
}

void muestra(DatosPersona a)
{
    printf("Me llamo %s y tengo %d años.\n", a.nombre, a.edad);
}

Ahora viene lo interesante. Hay que definir una interfaz en un fichero con extensión .i, en la que se dan a SWIG instrucciones para construir el envoltorio para usar el código.
Hay muchas posibilidades, (la documentación es muy extensa), y después de pasarme unas horillas buscando llegué a lo siguiente:
%module datosPersonales
%{
#include "datosPersonales.h"
%}

typedef struct {
  char nombre[150];
  int  edad;
}DatosPersona;

%extend DatosPersona
{
    DatosPersona(char *nombre, int edad)
    {
        DatosPersona *datos = (DatosPersona *) malloc(sizeof(DatosPersona));
        strcpy ( datos->nombre, nombre );
        
        datos->edad = edad;
        return datos;
    }
    
    ~DatosPersona() 
    { 
        free(self); 
    }
    
    int getEdad()
    { 
        edad_get( *self ); 
    }
    
    char * getNombre()
    { 
        return nombre_get( *self ); 
    }
    
    void setNombre(char *nombre)
    {
        nombre_set(self, nombre);
    }
    
    void setEdad(int edad)
    {
        edad_set(self, edad);
    }
    
    void muestraDatos()
    {
        muestra(*self);
    } 
};

En esta interfaz se extiende el tipo de datos de C con una serie de funciones miembro que nos permitirán usar orientación a objetos en Python.

Para compilar hice lo siguiente:
$ swig -python datosPersonales.i
$ ls
datosPersonales.c  datosPersonales.i   datosPersonales_wrap.c  
datosPersonales.h  datosPersonales.py
$ gcc -c datosPersonales.c
$ ls
datosPersonales.c  datosPersonales.i  datosPersonales.py
datosPersonales.h  datosPersonales.o  datosPersonales_wrap.c
$ gcc -c datosPersonales_wrap.c -I /usr/include/python2.5/
$ ls
datosPersonales.c  datosPersonales.i  datosPersonales.py datosPersonales_wrap.o 
datosPersonales.h  datosPersonales.o  datosPersonales_wrap.c
$ gcc -shared datosPersonales.o datosPersonales_wrap.o -o _datosPersonales.so
$ ls
datosPersonales.c  datosPersonales.i  datosPersonales.py   datosPersonales_wrap.c  
datosPersonales.h  datosPersonales.o  _datosPersonales.so  datosPersonales_wrap.o

Ahora ya está todo listo para poder usar el módulo datosPersonales.py desde Python.

import datosPersonales as dp

datos = dp.DatosPersona("Lolo", 34)

print datos.getEdad()
print datos.getNombre()

datos.muestraDatos()

datos.setNombre("Javi")
datos.setEdad(31)
datos.muestraDatos()

del datos

Y esto es lo que resulta al ejecutar el script:

$ python runMe.py 
34
Lolo
Me llamo Lolo y tengo 34 años.
Me llamo Javi y tengo 31 años.

Este ejemplo no deja de ser una tontería, pero las posibilidades de SWIG son grandísimas (sólo hay que ver algunos de los artículos online que aparecen en Internet).
Más adelante, si tengo algo de tiempo, me gustaría correr alguna simulación escrita en C desde Python y usar MatPlotLib para hacer los gráficos.

Friday, February 26, 2010

Cómo escribir código imposible de mantener

En How To Write Unmaintainable Code se describe una serie de pasos que debemos seguir para dificultar la mantenibilidad de nuestro código. Este irónico artículo, al que llegué desde una respuesta en un foro de Java llamado Java Ranch, puede ayudarnos a escribir código más fácil de mantener.

Thursday, February 25, 2010

Como poner letras griegas en un gráfico de Gnuplot

Usando el terminal Enhanced Postscript se pueden escribir un montón de símbolos usando una sintáxis parecida a la de Latex.

Existe una guía de dicha sintaxis en la que aparecen un montón de ejemplos.

En el siguiente gráfico utilicé la terminal EPS para poder usar letras griegas en las etiquetas de los ejes:


Este es el script que utilicé:
reset 
#Rango
set xrange [0:3]
set yrange [-2.5:4.5]
#Rango e intervalo de los xtics
set xtics -3,0.5,10
#Rango e intervalo de los ytics
set ytics -2.5,0.5,4.5

#Etiquetas de los ejes con letras griegas
set xlabel "t/{/Symbol p}"
set ylabel "{/Symbol q}"

#Se establece la posición de la leyenda
set key
#Se establece el origen
set origin 0,0
#Se establece el ratio entre el alto y el ancho del gráfico
set size ratio 0.5

#Se establece como terminal de salida un eps en color con letra Arial de tamaño 11
set term post eps enhanced color "Arial" 11

#Tamaño del gráfico
set size 1,1
#Con marco 
set border

#Fichero de salida
set output "theta.eps"

#Se plotean los datos
plot 'pos1.dat' using 1:2 title 'E=0.25' with lines, \
        'pos2.dat' using 1:2 title 'E=0.50' with lines, \
        'pos3.dat' using 1:2 title 'E=0.75' with lines, \
        'pos4.dat' using 1:2 title 'E=1.00' with lines, \
        'pos5.dat' using 1:2 title 'E=1.25' with lines
]]>

Gnuplot not so Frequently Asked Questions

Gnuplot not so Frequently Asked Questions es un sitio que contiene muchísimos trucos para mejorar la calidad de tus gráficos hechos con Gnuplot.
Me sirvió muchísimo mientras hacía la asignatura de Introducción a la Física Computacional.
-----
Gnuplot not so Frequently Asked Questions is a site that contains a lot of tips and shortcuts to improve your Gnuplot graphics.
It helped me a lot during the Introducction to Computacional Physics course.