Массив 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 
  • Python: ссылка на класс исключений, созданный с помощью PyErr_NewException в модуле расширения
  • Быстрое преобразование вектора C / C ++ в массив Numpy
  • Ошибка аргумента SWIG при использовании «using std :: vector» в python
  • Техника использования std :: ifstream, std :: ofstream в python через SWIG?
  • Как получить срез python для работы с моим классом массивов c ++ с помощью SWIG
  • SWIG в типографике работает, но аргумент не
  • Передача функций python в SWIG-код C ++
  • Python Properties & Swig
  • Python - лучший язык программирования в мире.