El lenguaje de programación C tiene muchos años que fue puesto a disposición de los desarrolladores de software, al ser un lenguaje compilado podemos hacer programas mucho más óptimos y rápidos, gracias a esto este lenguaje sigue aún en vigencia ya que permite realizar diferentes tipos de procesamientos de manera veloz.
En Python el poder de desarrollar de forma legible y amigable viene con un pequeño precio que es que se puede perder rendimiento en algunos procesos muy específicos, por lo que si esa pérdida no es aceptable y pone en riesgo nuestro programa debemos buscar alternativas. Su flexibilidad permite que podamos incorporar módulos hechos en otros lenguajes como C.
Escribir extensiones en C no es tan transparente como hacerlo en C# o en JAVA que con las diferentes implementaciones de Python lo hacemos muy rápido y fácil, con C debemos adherirnos a una API muy estricta, sin embargo estas dificultades han hecho que aparezcan herramientas que traten de mejorar este proceso, una de ellas es SWIG.
SWIG es un acrónimo para Simple Wrapper and Interface Generator es una herramienta que nos permite desarrollar extensiones en C o C++ y luego empaquetarlos para su uso en lenguajes de alto nivel como Python, Perl, Ruby y otros.
Para utilizar SWIG solo debemos cumplir unos simples pasos, veamos a continuación que necesitamos:
- Debemos escribir un interface para nuestro código en C, este tipo de archivo es muy similar a los headers; en algunos casos se puede utilizar el archivo header directamente.
- Corremos SWIG en el archivo interface, esto hace que se genere más código en C, es decir, el empaquetador.
- Compilamos el archivo interface junto con el empaquetador con lo que generamos una librería compartida que podremos utilizar con los lenguajes compatibles con SWIG.
Ya dominando un poco de teoría veamos ahora un ejemplo de esto que hemos explicado, vamos a realizar un módulo que detecte si un string es palindrome, es decir, que se lee de la misma forma en ambas direcciones, esto no es que represente un problema para Python, sin embargo cuando son strings realmente grandes ahí sí puede notarse el problema de rendimiento, vamos a ver primero el código en la siguiente imagen y luego ver cómo implementarlo usando SWIG:
Aquí tenemos la implementación en C, para saber si un string es palindrome, luego construimos la interface que es el siguiente código:
Ya que tenemos los requerimientos a nivel de C completos, de momento vamos a ver que debemos realizar en SWIG para poder utilizar esto:
Primero debemos correr el siguiente comando:
$ swig -python palindrome.iDonde palindrome.i es nuestra interface. Esto nos generará los archivos Python necesarios, luego debemos compilar todo, para este paso debemos saber muy bien las rutas de nuestros elementos para poder hacer las referencias correctas:
gcc -c palindrome.c gcc -I$PYTHON_HOME -I$PYTHON_HOME/Include -c palindrome_wrap.c gcc -shared palindrome.o palindrome_wrap.o -o _palindrome.soLuego de estos pasos ya podemos utilizar nuestra nueva librería en Python de la siguiente forma:
>>> import _palindrome >>> dir(_palindrome) ['__doc__', '__file__', '__name__', 'is_palindrome'] >>> _palindrome.is_palindrome('ipreferpi') 1 >>> _palindrome.is_palindrome('notlob') 0Con esto finalizamos el tutorial, como vemos es un poco complejo implementar extensiones en C sin embargo el rendimiento logrado lo vale.