extendiendo la matriz de variables c globales con swig y python

Tengo una matriz de variables globales en c que me gustaría incorporar a python. Y estoy teniendo dificultades con varout mapa de tipos:

/* example.c */
int foo[] = {0, 1};

Y aquí está la interfaz muy vainilla:

/* example.i */
%module example
%{     
 extern int foo[2];
%}

%typemap(varout) int foo[] {
  int i;
  //$1, $1_dim0, $1_dim1
  $result = PyList_New($1_dim0);
  for (i = 0; i < $1_dim0; i++) {
    PyObject *o = PyInt_FromLong((double) $1[i]);
    PyList_SetItem($result,i,o);
  }
}

%include "example.c"

Cuando intento construirlo con el siguiente SConstruct:

import distutils.sysconfig
env = Environment(SWIGFLAGS='-python -shadow -Wall'.split(),
                  CPPPATH=[distutils.sysconfig.get_python_inc()],
                  SHLIBPREFIX="")
env.SharedLibrary('_example.so', ['example.c', 'example.i'])

$1_dim0 la variable especial no se completa, lo que da como resultado el siguiente código no compilable en example_wrap.c:

SWIGINTERN PyObject *Swig_var_foo_get(void) {
  PyObject *pyobj = 0;

  {
    int i;
    //foo, , foo_dim1
    pyobj = PyList_New();
    for (i = 0; i < ; i++) {
      PyObject *o = PyInt_FromLong((double) foo[i]);
      PyList_SetItem(pyobj,i,o);
    }
  }
  return pyobj;
}

Claramente, la coincidencia del mapa de tipos ha ocurrido, pero falta la dimensionalidad de la matriz. ¿Qué me estoy perdiendo? La codificación dura de la dimensión funciona.

En general, ¿existe alguna forma de extender la cvar variables con trago?

$ swig -version
SWIG Version 2.0.4
Compiled with g++ [i686-pc-linux-gnu]
Configured options: +pcre
Please see http://www.swig.org for reporting bugs and further information

preguntado el 27 de julio de 12 a las 18:07

Mostré cómo hacer que su ejemplo funcione, pero no tengo claro lo que quiso decir con: "En general, ¿hay alguna forma de extender las variables cvar globales con swig?" - ¿Hay algo más en eso que simplemente arreglar el mapa de tipos? -

Me preguntaba si puedo extender el foo tipo variable con __getitem__() para hacerlo python scriptable con []. -

¿No es una PyList ya subscriptable? -

2 Respuestas

Ya casi estás allí con tu varout mapa tipográfico. Necesitas hacer dos cambios menores:

  1. Necesitas agregar el tamaño ANY En el correo electrónico “Su Cuenta de Usuario en su Nuevo Sistema XNUMXCX”. int foo[] mapa de tipos:

    %typemap(varout) int foo[ANY] {
      int i;
      //$1, $1_dim0, $1_dim1
      $result = PyList_New($1_dim0);
      for (i = 0; i < $1_dim0; i++) {
        PyObject *o = PyInt_FromLong((double) $1[i]);
        PyList_SetItem($result,i,o);
      }
    }
    

    Esto asegura que su mapa de tipos coincida con matrices de (cualquier) tamaño conocido, no solo equivalente a int *foo.

  2. Necesita modificar example.c para hacer el tamaño de foo más claro Es C legal y correcto tal como está, pero es complicado deducir el tamaño de la matriz a menos que sea un compilador completo de C. Cambiándolo a:

    int foo[2] = {0, 1};
    

    es suficiente para asegurarse de que coincide con el varout mapa tipográfico.

Con esos dos cambios, el código generado funciona como esperas:

SWIGINTERN PyObject *Swig_var_foo_get(void) {
  PyObject *pyobj = 0;

  {
    int i;
    //foo, 2, foo_dim1
    pyobj = PyList_New(2);
    for (i = 0; i < 2; i++) {
      PyObject *o = PyInt_FromLong((double) foo[i]);
      PyList_SetItem(pyobj,i,o);
    }
  }
  return pyobj;
}

es lo que se genera en mi máquina con esos cambios.

Respondido 27 Jul 12, 22:07

Para aquellos como yo que reflexionan sobre qué hacer con matrices de tipos no simples, esta es una forma de hacerlo:

El tipo no simple:

typedef struct {
    int a;
    float b;
} Foo;

y una matriz global:

extern Foo *foov[40];

%typemap(varout) Foo *foov[ANY] {
    int i;
    $result = PyList_New($1_dim0);
    for (i = 0; i < $1_dim0; i++) {
        PyObject *o = SWIG_NewPointerObj($1[i], SWIGTYPE_p_Foo, 0);
        PyList_SetItem($result, i, o);
  }
}

Acabo de compartir esto porque me tomó una eternidad descubrirlo, y este artículo me ayudó. Solo necesitaba averiguar cómo asignar la versión SWIG de mi tipo no simple; lo encontré enterrado aquí:

http://www.swig.org/Doc2.0/Python.html#Python_nn64

Respondido el 20 de diciembre de 15 a las 16:12

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.