Mam strukturę zdefiniowaną w header.H, który wygląda:

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

Kiedy init jest obiektem z tą strukturą, mam dostęp do liczby całkowitych / podwójnych, ale nie macierzy.

>> 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

Jak mieć dostęp do wartości w czytaniu / zapisu?

6
zeapo 13 listopad 2011, 23:25

3 odpowiedzi

Najlepsza odpowiedź

Najprostszym sposobem na to jest zawijanie tablic wewnątrz {x0}}, który może następnie zapewnić Dodatkowe metody spełniające" subskrybowane "wymagania.

Złożyłem mały przykład. Zakłada się, że używasz C ++, ale odpowiednikowa wersja C jest dość trywialna do konstruowania, tylko wymaga odrobiny powtórzeń.

Po pierwsze, nagłówek C ++, który ma struct, chcemy owinąć i szablon, którego używamy do owijania tablic o stałym rozmiarze:

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;

Nasz odpowiedni interfejs Swig wygląda w ten sposób:

%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>;

Sztuką jest to, że użyliśmy %extend, aby zasugerować {{ X1}}, który jest tym, co używa do czytania subskrypcji i {{ X2}} dla pisze. (Moglibyśmy również dostarczyć __iter__, aby zrobić typ Iteratable). Daliśmy również specyficzne wraped_array s chcemy użyć unikalnych nazw, aby switać je w wyjściu.

Dzięki dostarczonym interfejsie możemy teraz zrobić:

>>> 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

Możesz także znaleźć To podejście przydatne / interesujące jako alternatywa.

6
Community 23 maj 2017, 12:30

Zrobiłbym to w Pythonie

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 
3
Sam 24 lipiec 2012, 17:39

Czy rozważałeś za pomocą swig carrays?

W pliku nagłówka:

typedef struct {
    int      icntl[40];
    double   cntl[15];
} some_struct_t;

Następnie w pliku SWIG:

%module example
%include "carrays.i"  
// ...
%array_class(int, intArray);
%array_class(double, doubleArray);

Python wygląda tak:

icntl = example.intArray(40)
cntl = example.doubleArray(15)
for i in range(0, 40):
    icntl[i] = i
for i in range(0, 15):
    cntl[i] = i
st = example.some_struct_t()
st.icntl = icntl
st.cntl = cntl

Nadal nie możesz bezpośrednio ustawić struktury. Piszę kod opakowania Pythona, aby ukryć kotła.

Array_Class działa tylko z podstawowymi typami (int, podwójna), jeśli potrzebujesz czegoś innego (np. Uint8_t), musisz użyć array_functions, które mają jeszcze więcej kotła, ale działają.

http://www.swig.org/doc3.0/wigdocumentation.html#library_carrays.

0
Jonathan 19 październik 2019, 00:49