Массив SWIG / python внутри структуры

У меня есть структура, определенная внутри header.h, которая выглядит так:

typedef struct { .... int icntl[40]; double cntl[15]; int *irn, *jcn; .... 

Когда я инициализирую объект с этой структурой, у меня есть доступ к целым числам / парным разрядам, но не к массивам.

 >> st.icntl <Swig Object of type 'int *' at 0x103ce37e0> >> st.icntl[0] Traceback (most recent call last): File "test_mumps.py", line 19, in <module> print s.icntl[0] TypeError: 'SwigPyObject' object is not subscriptable 

Как получить доступ к значениям в режиме чтения / записи?

2 Solutions collect form web for “Массив SWIG / python внутри структуры”

Самый простой способ сделать это – обернуть ваши массивы внутри struct , которые затем могут предоставить дополнительные методы для удовлетворения «подзаменяемых» требований .

Я собрал небольшой пример. Предполагается, что вы используете C ++, но эквивалентная версия C довольно тривиальная, чтобы построить из этого, это просто требует немного повторения.

Прежде всего, заголовок C ++, который имеет struct мы хотим обернуть, и шаблон, который мы используем для упаковки массивов фиксированного размера:

 template <typename Type, size_t N> struct wrapped_array { Type data[N]; }; typedef struct { wrapped_array<int, 40> icntl; wrapped_array<double, 15> cntl; int *irn, *jcn; } Test; 

Соответствующий интерфейс SWIG выглядит примерно так:

 %module test %{ #include "test.h" #include <exception> %} %include "test.h" %include "std_except.i" %extend wrapped_array { inline size_t __len__() const { return N; } inline const Type& __getitem__(size_t i) const throw(std::out_of_range) { if (i >= N || i < 0) throw std::out_of_range("out of bounds access"); return self->data[i]; } inline void __setitem__(size_t i, const Type& v) throw(std::out_of_range) { if (i >= N || i < 0) throw std::out_of_range("out of bounds access"); self->data[i] = v; } } %template (intArray40) wrapped_array<int, 40>; %template (doubleArray15) wrapped_array<double, 15>; 

Фокус в том, что мы использовали %extend для поставки __getitem__ что и использует Python для чтения индексов и __setitem__ для записи. (Мы могли бы также предоставить __iter__ чтобы сделать тип итерабельным). Мы также дали конкретные wraped_array s, мы хотим использовать уникальные имена, чтобы заставить SWIG обернуть их в выходной файл.

Теперь с помощью поставляемого интерфейса мы можем:

 >>> import test >>> foo = test.Test() >>> foo.icntl[30] = -654321 >>> print foo.icntl[30] -654321 >>> print foo.icntl[40] Traceback (most recent call last): File "<stdin>", line 1, in <module> File "test.py", line 108, in __getitem__ def __getitem__(self, *args): return _test.intArray40___getitem__(self, *args) IndexError: out of bounds access 

Вы также можете найти этот подход полезным / интересным в качестве альтернативы.

Я бы сделал это в python

 ptr = int(st.icntl) import ctypes icntl = ctypes.c_int * 40 icntl = icntl.from_address(ptr) print icntl[0] icntl[0] = 1 for i in icntl: print i 
  • SWIG C ++ Python: обертывание int ссылкой или указателем
  • SWIG - Wring C строка строки в список python
  • Wrap C struct с элементом массива для доступа в python: SWIG? Cython? ctypes?
  • Python: SWIG vs ctypes
  • Сделать класс C ++ похожим на массив numpy с помощью swig
  • Использование distutils, где файл интерфейса swig находится в папке src
  • Swig downcasting from Base * to Derived *
  • Расширение Numpy с помощью функции C
  • Передача массива Python в c ++ с помощью SWIG
  • Ошибка аргумента SWIG при использовании «using std :: vector» в python
  • проблемы с установкой M2Crypto на Mint
  • Python - лучший язык программирования в мире.