Il modo più semplice per eseguire questa operazione è avvolgere gli array all'interno di uno struct
, che può quindi fornire extra methods to meet the "subscriptable" requirements.
Ho messo insieme un piccolo esempio. Presuppone che stai usando C++, ma la versione C equivalente è abbastanza semplice da costruire da questo, richiede solo un po 'di ripetizione.
Il primo, intestazione C++ che ha il struct
vogliamo avvolgere e un modello che usiamo per il confezionamento di array di dimensioni fisse:
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;
nostra interfaccia SWIG corrispondente appare quindi qualcosa di simile:
%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>;
Il trucco è che abbiamo usato %extend
per fornire __getitem__
che è ciò che Python usa per le letture degli indici e __setitem__
per le scritture. (Potremmo anche aver fornito un __iter__
per rendere il tipo iterabile). Abbiamo anche dato lo specifico wraped_array
s e vogliamo usare nomi univoci per fare in modo che SWIG li avvolga nell'output.
Con l'interfaccia in dotazione ora possiamo fare:
>>> 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
Si potrebbe anche trovare this approach utile/interessante come alternativa.