Esses dias estou trabalhando em uma biblioteca cross-platform de captura de vídeo em C++, e pensei em aproveitar a situação para continuar um projeto que eu tinha, o ruby-v4l. Então lembrei de um software que eu tinha ouvido falar, o SWIG, e resolvi fazer uns testes com ele. Ele é capaz de exportar automaticamente um código em C ou C++ para uso em diversas linguagens de script: PHP, Ruby, Python, Perl, Java, e diversas outras. Se a linguagem de destino permitir, ele exporta até mesmo operator overloading e outros recursos de C++.
Darei aqui um exemplo simples de uso do utilitário SWIG para exportar uma classe em C++ para o Python.
Primeiramente, vamos ao código em C++.
// teste.h
class vector {
public:
double x, y;
vector(double = 0, double = 0);
vector operator + (vector);
vector operator - (vector);
vector operator - ();
vector operator * (double);
double module();
};
// teste.cpp
using namespace std;
#include <cmath>
#include "teste.h"
vector::vector (double a, double b) {
x = a;
y = b;
}
vector vector::operator + (vector a) {
return vector(x + a.x, y + a.y);
}
vector vector::operator - (vector a) {
return vector(x - a.x, y - a.y);
}
vector vector::operator - () {
return vector(-x, -y);
}
vector vector::operator * (double a) {
return vector(x * a, y * a);
}
double vector::module() {
return sqrt(x*x + y*y);
}
Agora vamos criar um arquivo de instruções de exportação para o SWIG. Esse arquivo é mais ou menos no mesmo formato de um header C ou C++, com os protótipos das funções e classes que você queira exportar para a linguagem de destino.
// teste.i
%module teste
%{
#include "teste.h"
%}
class vector {
public:
double x, y;
vector(double = 0, double = 0);
vector operator + (vector);
vector operator - (vector);
vector operator - ();
vector operator * (double);
double module();
};
Agora é só rodar o SWIG para criar o wrapper para a linguagem de destino, no caso, Python:
$ swig -c++ -python teste.i
$ g++ -c -fpic teste.cpp teste_wrap.cxx -I /usr/include/python2.4
$ g++ -shared teste.o teste_wrap.o -o _teste.so
Agora teremos dois arquivos, teste.py, que é a interface de alto nível, e _teste.so, que é o wrapper com a interface de baixo nível. Podemos agora utilizar nosso código em C++ a partir do Python:
In [1]: import teste
In [2]: u = teste.vector(3,4)
In [3]: v = teste.vector(4,3)
In [4]: u.module()
Out[4]: 5.0
In [5]: v.module()
Out[5]: 5.0
In [6]: (u+v).module()
Out[6]: 9.8994949366116654
In [7]: (u-v).module()
Out[7]: 1.4142135623730951
In [8]: teste.vector(-1).module()
Out[8]: 1.0
In [9]: a = 2 * u
In [10]: (a.x, a.y)
Out[10]: (6.0, 8.0)
In [11]: a