Introduzindo o gcc-xml e o pygccxml

Nesse post vou falar de como usar duas ferramentas que estou usando para construir um gerador de wrappers managed para classes unmanaged. A primeira dela é o gcc-xml, que gera um arquivo xml a partir de um código C++ e a segunda é o pygccxml, um módulo Python que automatiza o processo de geração e também lê a saída carregando na forma de uma estrutura de dados conveniente para interpretação e consulta do código C++ lido.

Instalando o gcc-xml no Windows

Compilar o gcc-xml no Windows é uma tarefa bastante complicada e envolve configurar um ambiente para build que não é lá muito simples e bem documentado. Felizmente algumas pessoas que trabalham com projetos que usam essa ferramenta criaram instaladores para um binário já compilado. Até pouco tempo atrás a versão mais recente que eu tinha encontrado era um build da versão 0.7 feito em 2006 e hospedado na página do SourceForge do projeto ctypes. No entanto, no final do mês passado fiquei sabendo pela mailing list do projeto python-ogre que um instalador para a versão 0.9 estava disponível. Timing ideal para usar a ferramenta :-)

O instalador disponível é um desses instaladores comuns para Windows. Por padrão ele instala os arquivos na pasta "C:\Arquivos de programas\gccxml 0.9", mas você pode instalá-los em outro lugar se desejar. Os binários do programa se encontram na pasta "bin" dentro desse caminho.

gcc-xml-install.png

Depois disso, é conveniente adicionar o caminho para os binários (C:\Arquivos de programas\gccxml 0.9\bin, no caso do caminho de instalação padrão) à sua variável de ambiente PATH. Eu não irei mostrar aqui como fazer isso pois irá alongar o post com informação não tão relevante, mas é um processo muito simples e não é difícil de achar informações na Internet sobre isso.

Usando o gcc-xml

O gcc-xml é uma ferramenta de linha de comando. O seu uso é bastante semelhante com o de um compilador como o gcc, porém com algumas opções diferentes. Abaixo um screenshot do comando que eu usei para gerar um xml a partir de uma classe de matriz que eu criei para um projeto da cadeira de Computação Gráfica na faculdade.

gcc-xml-cmd.png

A opção -fxml=nome do arquivo indica o nome do arquivo onde a saída xml será gravada.

Os arquivos utilizados e o arquivo de saída estão disponíveis aqui aqui:

Usando o pygccxml

Ao abrir o xml gerado pelo gcc-xml dá para perceber que ele é bastante complicado. Apesar de xml ser um formato de arquivo padrão e com muitas bibliotecas disponíveis para processá-lo, para usar a saída do gcc-xml para algo útil é preciso entender a estrutura dele. Felizmente o pygccxml nos poupa muito desse trabalho porque ele já transforma o conteúdo desse xml em uma estrutura de dados com uma série de métodos úteis para obter as partes relevantes da estrutura do código C++.

Para ficar mais claro, vale um exemplo. Assumindo que você tem o binário do gcc-xml no seu PATH, o pygccxml irá encontrá-lo automaticamente. Em uma sessão interativa de Python eu usei a seguinte sequência de comandos para achar uma classe e listar seus métodos.

Mudar o diretório de trabalho para a localização dos meus arquivos C++ que eu queria processar.

>>> import os
>>> os.chdir('Z:\Meus documentos\Code\C++')
>>> 


Importar o submódulo parser e use a função parse passando uma lista de arquivos a serem processados. O legal é que não é necessário gerar o xml manualmente. O pygccxml já faz isso para você.

>>> from pygccxml import parser
>>> decls = parser.parse(['Matrix4.cpp'])
INFO Parsing source file "Matrix4.cpp" ... 
INFO gccxml cmd: ""Z:\Programas\gccxml 0.9\bin\gccxml.exe"  -I"."   "Matrix4.cpp" -fxml="c:\docume~1\kao\config~1\temp\tmpyx95kw.xml""
INFO GCCXML version - 0.9
>>> 


A variável 'decls' agora guarda uma lista de declarações. Depois importei o submódulo 'declarations' e usei uma função para obter o namespace global.

>>> from pygccxml import declarations
>>> global_ns = declarations.get_global_namespace(decls)
>>> 


A variável globalns agora contém uma estrutura de dados que representa um namespace C++ (o namespace global, nesse caso). Com o método 'class' dessa estrutura é possível obter uma classe segundo uma série de critérios definidos por parâmetros opcionais. Por exemplo, eu posso obter a classe Matrix4 da seguinte forma:

>>> mat4 = global_ns.class_(name='Matrix4')
>>>


Tendo acesso a classe eu posso também listar os seus métodos usando o método 'member_functions':

>>> for met in mat4.member_functions():
...     print met.name
...     
clear
clearIdentity
mult
>>> 


Pelos exemplo dá pra ver que é muito fácil obter informações sobre a estrutura de um código C++ através desse módulo. Isso faz com que ele seja a ferramenta ideal para fazer geração de wrappers para código C++. No próximo post falarei mais sobre o Cheetah Template e como ele pode ser usado em conjunto com o pygccxml para construir a ferramenta que de fato cria os wrappers managed para classes unmanaged.

Last edited Jan 5, 2009 at 8:12 PM by kcfelix, version 4

Comments

No comments yet.