L'idea che hai provato con [ANY]
non funzionerà per diversi motivi. Principalmente sebbene ANY
possa essere usato in typemaps per permettere alla stessa typemap di funzionare con array di dimensioni fisse variabili, che non è quello che hai lì.
Anche la sintassi per C non è sufficiente. Non si può scrivere:
int[4] bar() {
static int data[4];
return data;
}
Oppure:
int bar()[4] {
static int data[4];
return data;
}
In serie C. Il più vicino si può ottenere è:
int (*bar())[4] {
static int data[4] = {1,2,3,4};
return &data;
}
Ma questo non è davvero più facile per avvolgere.
Tuttavia, la soluzione più semplice può essere fatto funzionare utilizzando %array_class
, ad esempio:
%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);
Questo mi permette di fare:
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> >
>>>
Possiamo andare un passo migliore, anche se (forse) da iniettando il codice per nascondere automaticamente il puntatore al tipo di matrice, aggiungendo quanto segue prima che venga visualizzato bar()
da SWIG:
%pythonappend bar() %{
# Wrap it automatically
val = fooArray.frompointer(val)
%}
Così ora è possibile utilizzarlo come:
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
È necessario essere attenti a titolarità della memoria. In questi esempi finora la memoria è trapelata. Puoi usare %newobject
per dire a SWIG che la memoria è di proprietà di Python, ma poi verrà rilasciata troppo presto (non appena il valore di ritorno originale non sarà più referenziato) quindi dovrai organizzarti per mantenere il valore originale intorno più a lungo. Un esempio completo di questo, che salva il puntatore originale all'interno l'istanza della classe array di mantenere un riferimento intorno finchè l'involucro matrice stessa sarebbe:
%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);
Avviso però che la classe array questo genera è illimitato , esattamente come un struct foo*
in C. Ciò significa che non è possibile eseguire iterazioni su di esso in Python - la dimensione è sconosciuta.Se la dimensione è veramente corretta, o se hai un modo per conoscere la dimensione, in qualche modo puoi avvolgerla in un modo molto più bello (a mio avviso) scrivendo una typemap che restituisce una PyList. È un po 'più di lavoro da scrivere, ma rende l'interfaccia più bella sul lato Python.
Hai guardato qui? - http://stackoverflow.com/questions/8114030/swig-python-array-inside-structure – dpandiar
@dpandiar - questo è un caso piuttosto diverso perché la dimensione è fissa e nota e gli array sono membri e non restituiscono valori da una funzione – Flexo