Pomysł, który wypróbowałeś z [ANY]
, nie zadziała z kilku powodów. Przede wszystkim jednak można używać ANY
w mapach typów, aby ta sama mapa działała z różnymi tablicami o stałym rozmiarze, co nie jest tym, co tam masz.
Składnia C nie jest tam również odpowiednia. Nie możesz napisać:
int[4] bar() {
static int data[4];
return data;
}
czyli
int bar()[4] {
static int data[4];
return data;
}
W standardowym C najbliżej można dostać się:
int (*bar())[4] {
static int data[4] = {1,2,3,4};
return &data;
}
Ale to naprawdę nie jest łatwiejsze do zawijania.
jednak proste rozwiązanie może być wykonane do pracy z użyciem %array_class
, na przykład:
%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);
pozwala to mi zrobić:
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> >
>>>
Możemy pójść o krok lepsza (ewentualnie) przez wstrzykiwanie kodu w celu automatycznego ukrywania wskaźnika na typie macierzy, dodając następujące wartości przed wyświetleniem bar()
przez SWIG:
%pythonappend bar() %{
# Wrap it automatically
val = fooArray.frompointer(val)
%}
Więc można teraz używać jak:
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
Trzeba być ostrożnym o własności pamięci. W tych przykładach do tej pory pamięć wycieka. Możesz użyć %newobject
, aby poinformować SWIG, że pamięć jest własnością strony Python, ale potem zostanie ona wydana zbyt wcześnie (tak szybko, jak pierwotna wartość zwracana nie będzie już przywoływana), więc musisz zachować oryginalną wartość wokół dłużej. Kompletny przykładem tego, co oszczędza pierwotnego wskaźnika wewnątrz przykład klasy tablicy zachować odniesienie tak długo, jak owijki tablicy sam będzie:
%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);
Wskazówki jednak, że klasa Tablica ta generuje jest nieograniczona , dokładnie tak, jak w przypadku C struct foo*
. Oznacza to, że nie można go iterować w języku Python - rozmiar jest nieznany.Jeśli rozmiar jest rzeczywiście ustalony lub masz sposób poznania rozmiaru, możesz jakoś zawinąć to w znacznie ładniejszy (moim zdaniem) sposób, pisząc mapę typów, która zwraca PyList. Pisanie jest nieco bardziej pracochłonne, ale sprawia, że interfejs wygląda ładniej po stronie Pythona.
Czy spojrzałeś tutaj? - http://stackoverflow.com/questions/8114030/swig-python-array-inside-structure – dpandiar
@dpandiar - to całkiem inny przypadek, ponieważ rozmiar jest ustalony i znany, a tablice są członkami i nie zwracają wartości z funkcji – Flexo