Aqui estou novamente, agora tentando mostrar pra vocês como fazer C conversar com Python. Ao invés de explicar passo a passo como fazer e repetir um monte de documentação que já está no oráculo google, vou simplesmente colar um exemplo com algumas funções e comentários.
Esse exemplo pode servir como template pra o que você está tentando fazer.
Primeiro abra um arquivo chamado avatymodule.c. É convenção sempre usar o nome ‘module’ depois do real nome do módulo. Se você for chamar o módulo de tuxcool, o nome do arquivo deverá ser tuxcoolmodule.c.
Abaixo vai o código do avatymodule.c com alguns comentários:
#include "Python.h" // Assinatura do nosso modulo void initavaty(void); // Função principal que embute o python dentro do C. main(int argc, char **argv) { // Inicializa o Interpretador python embutido Py_Initialize(); // Adiciona o nosso modulo initavaty(); // Sai do interpretador embutido. Py_Exit(0); } /* Aqui vão as funções do nosso módulo. Todas que fiz seguiram um modelo. */ /* Note que o nome da função sempre vem com [NOME_DO_MODULO]_[NOME_DA_FUNCAO]. Esse metodo apenas da um 'hello world' usando o printf e o print do python. */ static PyObject *avaty_hello_world(PyObject *self, PyObject* args) { PyRun_SimpleString("import time\n"); PyRun_SimpleString("print '[Py] Aqui eh Python:',time.time()"); return Py_None; } static PyObject *avaty_argumento_numeros(PyObject *self, PyObject* args) { long numero1, numero2, soma; /* A função PyArg_ParseTuple() é responsável pela transição de argumentos das funções em python para tipos C. */ if (!PyArg_ParseTuple(args, "ll:addi", &numero1, &numero2)) { return NULL; } // Note que já trato numero1 e numero2 como long C. soma = numero1 + numero2; // Transformando e retornando o resultado da soma em um long Python. return PyLong_FromUnsignedLong(soma); } static PyObject *avaty_argumento_string(PyObject *self, PyObject* args) { char *str1, str2[15] = "str_c"; if (!PyArg_ParseTuple(args, "s:addi", &str1)) { return NULL; } strcat(str2, str1); return PyString_FromString(str2); } /* Aqui vai uma estrutura com todas as funções dos módulos. Observe que é convenção usar o nome da função python igual a função C. */ static PyMethodDef avaty_methods[] = { {"hello_world",avaty_hello_world,METH_NOARGS, "Documentação do hello world!"}, {"argumento_numeros",avaty_argumento_numeros,METH_VARARGS, "Documentação do argumento_numeros"}, {"argumento_string",avaty_argumento_string,METH_VARARGS, "Documentação do argumento_numeros"}, {NULL, NULL} //sentinela }; /* Função para importar o módulo dentro do interpretador embutido, que foi inicializado no main. */ void initavaty(void) { PyImport_AddModule("avaty"); Py_InitModule("avaty", avaty_methods); }
Calma, calma. Eu sei que o highlight ficou uma bosta e você não tá conseguindo entender nada. Coloquei o código aqui no pastebin.com e aqui pra você baixar também.
Agora, tudo que você precisa fazer é gerar um script de build, que nesse exemplo chamarei de buildscript.py (gostou do nome?
)
flavio@avaty:~/dev/bindings$ cat buildscript.py
from distutils.core import setup, Extensionsetup(name=”avaty”, version=”1.0″, ext_modules=[Extension("avaty", ["avatymodule.c"])])
flavio@avaty:~/dev/bindings$
Pronto, agora é só dar:
flavio@avaty:~/dev/bindings$ python buildscript.py build_ext -i
running build_ext
building ‘avaty’ extension
gcc -pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions build/temp.linux-i686-2.5/avatymodule.o -o avaty.so
flavio@avaty:~/dev/bindings$ file avaty.so
avaty.so: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked, not stripped
Note que um avaty.so vai ter sido criado. Agora é só experimentar se o negócio funcionou mesmo:
flavio@avaty:~/dev/bindings$ python
Python 2.5.2 (r252:60911, Oct 5 2008, 19:24:49)
[GCC 4.3.2] on linux2
Type “help”, “copyright”, “credits” or “license” for more information.
>>> import avaty
>>> dir(avaty)
['__doc__', '__file__', '__name__', 'argumento_numeros', 'argumento_string', 'hello_world']
>>> avaty.hello_world()
[C] Opa, aqui eh C, e usei o printf.
[Py] Aqui eh Python: 1231955166.34[C] Aqui é C também.
>>> avaty.argumento_numeros(4,30)
[C] Primeiro Argumento: 4
[C] Segundo Argumento: 30
34L
>>> retorno = avaty.argumento_string(”_to_py”)
[C] Recebido array de caracteres: _to_py
[C] Contatenacao usando strcat() com: str_c
[C] Retornando resultado pra objeto string python: str_c_to_py
>>> print retorno
str_c_to_py
>>> print type(retorno)
<type ’str’>
>>>
Ainda preciso olhar melhor o argumento format da função PyArg_ParseTuple() mas acredito que o conteúdo desse post já serve como pontapé inicial pra muita gente.
Pra finalizar, indico a leitura da Python/C API, pra facilitar no uso de funções de transformação de valores C <-> Python.
UPDATE: O link pra download do modulo agora funciona. ![]()


January 15th, 2009 at 12:48 am
[...] nosso modulo. initavaty();. // Sai do interpretador embutido. Py_Exit(0); … fique por dentro clique aqui. Fonte: [...]
February 19th, 2009 at 3:24 pm
[...] Fonte: http://www.pythonbrasil.com.br/moin.cgi/InicieSe, http://br-linux.org/linux/node/2543, http://pt.wikipedia.org/wiki/Python, http://www.flavioribeiro.com/v2.0/2009/01/14/extendendo-python-com-c/ [...]
March 5th, 2009 at 4:54 am
Cara, acabei de ler alguns posts seus no Planet, todos muito bons.
Parabéns pelo conteúdo de qualidade.
March 5th, 2009 at 6:33 am
Brigado pela visita e o elogio Rodrigo.
Abraço!
March 7th, 2009 at 10:58 pm
Tentei seguir o tutorial, mas tive problema logo de cara no include, onde fica o Python.h no linux? Precisa baixar algo?
Ótimo blog. =D
March 8th, 2009 at 3:36 pm
Fala Fábio, esqueci de colocar no ‘tutorial’ que é preciso ter o pacote python-dev (isso se estivermos falando de distribuições baseadas em debian, como o meu ubuntu).
Enfim, dá um aptitude install python-dev que acho que as coisas vão funcionar.
Abraço e obrigado pela visita
March 9th, 2009 at 6:14 am
Brigado Flávio, vou testar aqui depois.
March 10th, 2009 at 4:47 pm
Deu tudo certo aqui Flávio =D
Vou tentar me aprofundar mais.
March 11th, 2009 at 5:36 pm
Legal Fábio, extensões c\python vão muito mais a fundo do que esse template.. ai eu só fiz transformações de strings e inteiros, a parte carregada fica em cima de instanciar objetos, chamar métodos de uma linguagem em outra e etc.
Bom estudo!