La idea que ha intentado con [ANY]
no funcionará por varias razones. Sin embargo, principalmente, ANY
se puede usar en mapas de tipos para permitir que el mismo mapa de tipos funcione con varias matrices de tamaño fijo, que no es lo que tienes allí.
La sintaxis para C no está allí tampoco. No se puede escribir:
int[4] bar() {
static int data[4];
return data;
}
O:
int bar()[4] {
static int data[4];
return data;
}
En estándar de C. Lo más cerca que se puede obtener es:
int (*bar())[4] {
static int data[4] = {1,2,3,4};
return &data;
}
Pero eso no es realmente más fácil para envolver.
Sin embargo, la solución simple puede hacerse funcionar usando %array_class
, por ejemplo:
%module test
%inline %{
struct foo {
int member;
};
struct foo *bar() {
struct foo *arr = malloc(sizeof(struct foo) * 4);
for (int i = 0; i < 4; ++i)
arr[i].member = i;
return arr;
}
%}
%include <carrays.i>
%array_class(struct foo, fooArray);
Esto me permite hacer:
Python 3.2.3 (default, May 3 2012, 15:54:42)
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import test
>>> arr = test.fooArray.frompointer(test.bar())
>>> arr
<test.fooArray; proxy of <Swig Object of type 'fooArray *' at 0xb6f332a8> >
>>> arr[0]
<test.foo; proxy of <Swig Object of type 'struct foo *' at 0xb6f33038> >
>>> arr[1]
<test.foo; proxy of <Swig Object of type 'struct foo *' at 0xb6f33380> >
>>> arr[2]
<test.foo; proxy of <Swig Object of type 'struct foo *' at 0xb6f33398> >
>>> arr[3]
<test.foo; proxy of <Swig Object of type 'struct foo *' at 0xb6f330c8> >
>>>
podemos ir un paso más, aunque (posiblemente) por inyectando el código para encubrir el puntero al tipo de matriz automáticamente, agregando lo siguiente antes de bar()
es visto por SWIG:
%pythonappend bar() %{
# Wrap it automatically
val = fooArray.frompointer(val)
%}
Así que ahora puede utilizarlo como:
Python 3.2.3 (default, May 3 2012, 15:54:42)
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import test
>>> test.bar()[1].member
1
>>> arr = test.bar()
>>> arr[3].member
3
Es necesario tener cuidado con la propiedad de memoria. En estos ejemplos, hasta ahora se ha filtrado la memoria. Puede usar %newobject
para decirle a SWIG que la memoria pertenece al lado de Python, pero luego se liberará demasiado pronto (tan pronto como ya no se haga referencia al valor de retorno original), por lo que tendría que organizarse para mantener el valor original más. Un ejemplo completo de eso, lo que guarda el puntero original, dentro de la instancia de la clase matriz para mantener una referencia en todo el tiempo que la envoltura propia matriz sería:
%module test
%pythonappend bar() %{
# Wrap it automatically
newval = fooArray.frompointer(val)
newval.ptr_retain = val
val = newval
%}
%newobject bar();
%inline %{
struct foo {
int member;
};
struct foo *bar() {
struct foo *arr = malloc(sizeof(struct foo) * 4);
for (int i = 0; i < 4; ++i)
arr[i].member = i;
return arr;
}
%}
%include <carrays.i>
%array_class(struct foo, fooArray);
Aviso pesar de que la clase Array esto genera es ilimitada , exactamente como struct foo*
en C. Esto significa que no puede iterar sobre él en Python: el tamaño es desconocido.Si el tamaño es realmente fijo, o si tiene alguna forma de conocer el tamaño de alguna manera, puede envolverlo de una forma mucho más agradable (a mi modo de ver) escribiendo un mapa de tipos que devuelva una lista PyList. Es un poco más difícil de escribir, pero hace que la interfaz parezca mejor en el lado de Python.
¿Has visto aquí? - http://stackoverflow.com/questions/8114030/swig-python-array-inside-structure – dpandiar
@dpandiar - ese es un caso completamente diferente porque el tamaño es fijo y conocido y las matrices son miembros y no devuelven valores de una función – Flexo