Librer铆as de ayuda a la generaci贸n del glue code

Swig

Swig (Simplified Wrapper and Interface Generator) es una herramienta que se utiliza para integrar sistemas de scripts a programas C/C++. Los sistemas de scripts soportados son varios a ser:

. Perl
. Python
. Tcl
. Guile
. MzScheme
. Ruby
. Java

En las 煤ltimas versiones se agreg贸 soporte a:

. PHP
. Objective Caml
. Pike
. C#
. Chicken
. Allegro CL
. Modula 3

Swig puede ser descargado desde http://www.swig.org y puede ser utilizado libremente. La herramienta es b谩sicamente un precompilador, de uso muy similar a ToLua, s贸lo que en este caso no existe una librer铆a con la cual enlazar.
En funci贸n del sistema de scripts que se desee integrar se soportan diversas funcionalidades de C++. En este caso, nuestro inter茅s pasa por integrar Python utilizando Swig y por suerte la integraci贸n que hace Swig con este sistema est谩 muy trabajada y fue incorporada en las primeras versiones de la utilidad.
Se soportar谩 de C++ las siguientes funcionalidades:

. Todos los tipos de datos del C++
. Referencias
. Punteros a miembros
. Clases
. Herencia y herencia m煤ltiple
. Sobrecarga de funciones y m茅todos
. Sobrecarga de operadores
. Miembros est谩ticos
. Espacios de nombre
. Templates

Con esto queremos decir, que las funcionalidades mencionadas de C++ ser谩n de alg煤n modo mapeadas en Python para poder ser explotadas.

Pero veamos un ejemplo en acci贸n. Mencionamos que su uso era similar a ToLua, aqu铆 tambi茅n deberemos crear un archivo cabecera de declaraci贸n de una clase simplificado, en este caso se su terminaci贸n ser谩 “.i”. Este archivo ser谩 tomado por el precompilador el cual dejar谩 como salida un archivo tipo C++ que deber谩 ser compilado con nuestro proyecto.

Tambi茅n, para acceder a ciertas funcionalidades, podemos requerir la generaci贸n de clases especiales en Python llamadas shadow classes, estas clases son la contra parte de las clases C++ a la cuales queremos acceder. De este modo podremos hacer referencia a ellas desde Python como si fuesen nativas y se podr谩n manejar objetos C++ como si fuesen de Python (con la contra de introducir una indirecci贸n extra).

Una vez creado el archivo del tipo .i deberemos utilizar la herramienta swig para generar el archivo c++ del siguiente modo:

swig -c++ -python -shadow -o clasefoo.cxx clasefoo.i

El modificador -c++ indica que el c贸digo a generar es C++, el -python indica que el lenguaje objetivo es Python, luego especificamos que genere shadow classes con -shadow y finalmente especificamos el archivo de salida con -o.

Tambi茅n podremos configurar el entorno Visual Studio .NET para que la herramienta sea invocada autom谩ticamente cuando estamos construyendo el proyecto.
Para esto deberemos realizar los siguientes pasos:

1. Incluir el archivo i en nuestro proyecto.

2. Mover el archivo en el panel “Solution Explorer” desde “Solutions Items” a “Source Files”:

3. Acceder a las propiedades del archivo clasefoo.i y en la secci贸n “Custom Build Setup” agregar en:

CommandLine: swig -c++ -python -shadow -o $(InputName).cxx $(InputName).i
$(InputName) es una variable que representa el nombre del archivo.

Description: Precompilando con Swig
Aqu铆 podremos especificar la descripci贸n que deseemos (este mensaje aparecer谩 en la ventana “Output” cuando el entorno de desarrollo est茅 trabajando en la construcci贸n del proyecto).

Outputs: $(ProjectDir)/$(InputName).cxx
Indicamos cual ser谩 el nombre y ubicaci贸n del archivo de salida.

4. Precompilado por primera vez el archivo pkg, agregamos su salida al proyecto (el archivo del tipo cxx) para que sea compilado convenientemente.

Ahora, vamos a utilizar la misma clase que utilizamos en el ejemplo de ToLua:

Archivo: ClaseFoo.h

| class ClaseFoo
| {
| public:
| ClaseFoo();
| ~ClaseFoo();
|
| int m_valor;
|
| void SetValor(int iVal);
| int GetValor();
| };

El archivo de interfaz va a ser bastante similar al de ToLua, veamos:


| %module clasefoo
| %{
| #include "ClaseFoo.h"
| %}
|
| class ClaseFoo
| {
| public:
| ClaseFoo();
| ~ClaseFoo();
| static int m_svalor;
| int m_valor;
| void SetValor(int iVal);
| int GetValor();
| };

Podemos apreciar que tambi茅n introducimos un #include para que sea pasado directamente y sin interpretaci贸n al archivo generado.

Cuando swig entre en acci贸n generar谩 un archivo similar al que se muestra a continuaci贸n:


| /* ----------------------------------------------------------------------------
| * This file was automatically generated by SWIG (http://www.swig.org).
| * Version 1.3.23
| *
| * This file is not intended to be easily readable and contains a number of
| * coding conventions designed to improve portability and efficiency. Do not make
| * changes to this file unless you know what you are doing--modify the SWIG
| * interface file instead.
| * ----------------------------------------------------------------------------- */
|
| #define SWIGPYTHON
|
| #ifdef __cplusplus
| template<class T> class SwigValueWrapper
| {
| T *tt;
| public:
| SwigValueWrapper() : tt(0) { }
| SwigValueWrapper(const SwigValueWrapper<T>& rhs) : tt(new T(*rhs.tt)) { }
| SwigValueWrapper(const T& t) : tt(new T(t)) { }
| ~SwigValueWrapper() { delete tt; }
| SwigValueWrapper& operator=(const T& t) { delete tt; tt = new T(t); return *this; }
| operator T&() const { return *tt; }
| T *operator&() { return tt; }
| private:
| SwigValueWrapper& operator=(const SwigValueWrapper<T>& rhs);
| };
| #endif
|
| #ifndef SWIG_TEMPLATE_DISAMBIGUATOR
| # if defined(__SUNPRO_CC)
| # define SWIG_TEMPLATE_DISAMBIGUATOR template
| # else
| # define SWIG_TEMPLATE_DISAMBIGUATOR
| # endif
| #endif
|
| #include <Python.h>
|
| /***********************************************************************
| * common.swg
| *
| * This file contains generic SWIG runtime support for pointer
| * type checking as well as a few commonly used macros to control
| * external linkage.
| *
| * Author : David Beazley (beazley@cs.uchicago.edu)
| *
| * Copyright (c) 1999-2000, The University of Chicago
| *
| * This file may be freely redistributed without license or fee provided
| * this copyright message remains intact.
| ************************************************************************/
|
| #include <string.h>
| // ...

Del archivo generado, s贸lo mostramos una secci贸n ya que el archivo real pose铆a 1450 l铆neas de c贸digo (!).

Conclusi贸n

Luego de haber decidido utilizar un sistema de scripts como Python, Lua o el que fuese podremos hacer uso de algunas de las opciones que mencionamos en este art铆culo (o soluciones similares para otros lenguajes). Sin embargo, siempre existe quien opine que es mejor hacer todo el trabajo a mano y que el c贸digo compilado en nuestro proyecto sea exclusivamente generado por nosotros y no por un sistema gen茅rico no optimizado para uso en juegos; al menos esta fue la opini贸n que escuch茅 alguna vez de un respetado colega de la industria. Es cuesti贸n de probar, al fin y al cabo todo el c贸digo generado por estos precompiladores pueden ser analizados por nosotros las veces que sean necesarias.

Compartir:
  • Twitter
  • Facebook
  • MySpace
  • BarraPunto
  • del.icio.us

Pages: 1 2

Comments

  1. Novack
    December 8th, 2007 | 0:40

    Bueno la verdad todavia no he hecho tiempo para leerlos completos, pero ante el esfuerzo, no puedo dejar de comentar :)

    Buen laburo!

Leave a reply