SWIG/python array inside structure
Question: I've got a structure defined inside header.h that looks like :

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

When I init an object with this structure, I have access to integers/doubles
but not arrays.

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

How to have access to the values in read/write?


Answer: The easiest way to do this is to wrap your arrays inside a `struct`, which can
then provide [extra methods to meet the "subscriptable"
requirements](http://stackoverflow.com/questions/216972/in-python-what-does-
it-mean-if-an-object-is-subscriptable-or-not).

I've put together a small example. It assumes you're using C++, but the
equivalent C version is fairly trivial to construct from this, it just
requires a bit of repetition.

First up, the C++ header that has the `struct` we want to wrap and a template
that we use for wrapping fixed size arrays:

    
    
    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 then looks something like:

    
    
    %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 there is that we've used `%extend` to supply
[`__getitem__`](http://docs.python.org/reference/datamodel.html#object.__getitem__)
which is what Python uses for subscript reads and
[`__setitem__`](http://docs.python.org/reference/datamodel.html#object.__setitem__)
for the writes. (We could also have supplied a `__iter__` to make the type
iteratable). We also gave the specific `wraped_array`s we want to use unique
names to make SWIG wrap them in the output.

With the supplied interface we can now do:

    
    
    >>> 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 might also find [this
approach](http://www.swig.org/Doc1.3/Python.html#Python_nn63)
useful/interesting as an alternative.

