Sunday, April 3, 2011

Extendiendo C con Python 2: Retornando vectores

En un post anterior les comenté que se podía ocupar C desde Python de una manera muy chora, dando pie a crear librerías rápidas y eficientes.

La pregunta que quedó en el aire en ese post era cómo pasar vectores creados en C a Python. Aunque dejé un comentario en ese post, quería hacer hincapié en un problema que tuve unos días atrás con la solución que postié allí.

En primera instancia, yo pensé que retornar un vector que llamaremos "theArray" era solamente crear un "objecto Python" (estructura en C) y pasarlo como objeto en Py_BuildValue(), como la respuesta que había dado en ese post. Pero trabajando con dichó código, me di cuenta que había un problema de memoria, por lo que el código que está arriba es incorrecto. Ahora, la pregunta era por qué.

Algunas personas me hicieron ver que en la documentación de la función Py_BuildValue(), sale que esta agrega una referencia al objeto que retorna (en este caso la lista myList). Las referencias son usadas en Python para liberar memoria por una función interna llamada "Garbage Collector". La idea es que si quiero usar algo siempre, "referencio" ese objeto y así no se borra de la memoria, pero si no lo uso lo "derreferencio" y será eventualmente borrado de la memoria (entendiéndose "borrar" como "liberar" ese espacio en la memoria). Esto se hace internamente en varias funciones, pero el tema está en que si algo esta "referenciado", no se borra de la memoria (es como una manera eficiente de guardar y borrar memoria, de modo de no andar haciendo "free()" todo el rato, como en C).

¿La solución? Quitarle la referencia al objeto antes de enviarlo con la función Py_DECREF(). Para ver como era en detalle, vean el post que hize en StackOverflow acá: http://stackoverflow.com/questions/5508904/c-extension-in-python-return-py-buildvalue-memory-leak-problem

No comments:

Post a Comment