Hace algún tiempo estaba desarrollando un módulo para python, con el cual aprendí bastante y sirvió para crear una serie de artículos sobre el tema (Crear un módulo para python con la Python C API). Uno de los problemas encontrados fue cómo conseguir pasar un array de structs desde C a Python, para resolver la duda pregunté, cómo no, en stackoverflow. Al final terminé respondiéndome a mí mismo, pero aprendí bastante, veamos cómo hacerlo.



El struct a pasar puede ser cualquiera, pero en el ejemplo concreto era este:

struct tcpstat
{
    inet_prefix local;
    inet_prefix remote;
    int     lport;
    int     rport;
    int     state;
    int     rq, wq;
    int     timer;
    int     timeout;
    int     retrs;
    unsigned    ino;
    int     probes;
    unsigned    uid;
    int     refcnt;
    unsigned long long sk;
    int     rto, ato, qack, cwnd, ssthresh;
};

La solución consiste en crear un objeto PyListObject y un PyObject. Éste último lo usaremos como un diccionario y será donde iremos añadiendo los datos necesarios del struct. De esta forma estamos construyendo una lista cuyos elementos son diccionarios, algo así:

[
   {'clave1': 'valor1',  # Diccionario 1, con dos elementos.
    'clave1_2': 'valor1_2'},
   {'clave2' : 'valor2'}, # Diccionario 2, con un elemento.
   {'clave3' : 'valor3',
    #........ : .......,
    'claven' : 'valorn'}, # Diccionario 3, con N elementos.
]

El código es el siguiente:

PyObject *dict = NULL;
PyListObject *list;

list = (PyListObject *) Py_BuildValue("[]");

int i = 0;
for (i; i < stats_length; i++) {
    dict = Py_BuildValue("{s:i}", "LPort", stats[i].lport);
    PyList_Append(list, dict);
}

return (PyObject *) list;

En el ejemplo sólo se está almacenando un campo del struct, para almacenar más, simplemente habría que modificar la línea por:

dict = Py_BuildValue("{"
                     "   s:i,"
                     "   s:i"
                     "}",
                        "Dir Local.", stats[i].lport,
                        "Dir Remota.", stats[i].rport);

Y continuar rellenando el diccionario según nuestras necesidades.

Referencias

Python C API How to pass array of structs from C to Python »» stackoverflow.com

Índice