The easiest way to do this is to wrap arrays inside a struct , which can then provide additional methods to satisfy the "signature" requirements .
I put together a small example. It is assumed that you are using C ++, but the equivalent version of C is pretty trivial to build from this, it just requires a little repetition.
First, the C ++ header, which has a struct that we want to wrap, and the template that we use to pack arrays of fixed size:
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;
Our corresponding SWIG interface looks something like this:
%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>;
The trick is that we used %extend to supply __getitem__ , which Python uses to read substrings and __setitem__ to write. (We could also put __iter__ to make the type iterable). We also gave a specific wraped_array that we want to use unique names to force SWIG to wrap them in the output file.
Using the supplied interface, we can now:
>>> 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
You can also find this approach useful / interesting as an alternative.