nested structure array access in python using SWIG

限于喜欢 提交于 2019-12-06 07:53:50
Flexo

You can wrap this header without having to modify it buy doing something like:

%module status

%immutable;
%inline %{
template <typename Type, size_t N>
struct wrapped_array {
  Type (&data)[N];
  wrapped_array(Type (&data)[N]) : data(data) { }
};
%}
%mutable;

%{
#include "status.h"
%}

%include "typemaps.i"
%include "std_except.i"

// Only expose a reduced STATUS, without the Array:
typedef struct
{
    UCHAR  qrs;
    UCHAR  tuv;
    LONG   wxy;
} STATUS;

%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 (SubStatusArray) wrapped_array<SUB_STATUS,4>;

// Hide the real array in our helper

%extend STATUS {
  wrapped_array<SUB_STATUS,4> getSubStatus() {
    return wrapped_array<SUB_STATUS,4>($self->SubStatus);
  }
}

%ignore STATUS; // We've specified an alternative way of wrapping this
%include "status.h"

This is basically the same as my answer here, but instead of modifying the header to use the wrapped_array, we've used %ignore to tell SWIG we will supply our own definition of STATUS for it to wrap. (This is perfectly legal, the SWIG generated wrapper will still use the real definition from status.h)

We inject into this altered definition a getSubStatus(), which returns an object that acts as a proxy to the real array in STATUS. This proxy in turn supplies __getitem__, __setitem__ and __len__ that python looks for to use the subscript operator.

There might be a way to do this properly in Python without needing the getSubStatus(), making SWIG set __swig_setmethods__["SubStatus"] and __swig_getmethods__["SubStatus"] appropriately, but I'm not sure off the top of my head how to make SWIG python do that.

If you're using C, not using C++ you'll want to drop the template in favour of just a plain struct and use a pointer instead of a reference to an array.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!