结构内部的 SWIG/python 数组 [英] SWIG/python array inside structure

查看:52
本文介绍了结构内部的 SWIG/python 数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 header.h 中定义了一个结构,如下所示:

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

当我用这种结构初始化一个对象时,我可以访问整数/双精度数,但不能访问数组.

<代码>>>st.icntl<0x103ce37e0 处类型为int *"的 Swig 对象>>>st.icntl[0]回溯(最近一次调用最后一次):文件test_mumps.py",第 19 行,在 <module> 中打印 s.icntl[0]类型错误:SwigPyObject"对象不可下标

如何访问读/写中的值?

解决方案

最简单的方法是将数组包装在 struct 中,然后可以提供 满足可订阅"要求的额外方法.

我整理了一个小例子.它假设您使用的是 C++,但是从它构建等效的 C 版本相当简单,只需要一些重复.

首先,包含我们要包装的 struct 的 C++ 头文件和用于包装固定大小数组的模板:

template 结构包裹数组{类型数据[N];};类型定义结构{包裹数组icntl;Wrapped_arraycntl;int *irn, *jcn;} 测试;

我们对应的 SWIG 界面如下所示:

%module 测试%{#include "test.h"#include <例外>%}%include "test.h"%include "std_except.i"%extendwrapped_array {内联 size_t __len__() const { return N;}内联常量类型&__getitem__(size_t i) const throw(std::out_of_range) {如果 (i >= N || i < 0)throw std::out_of_range("越界访问");返回 self->data[i];}内联 void __setitem__(size_t i, const Type& v) throw(std::out_of_range) {如果 (i >= N || i < 0)throw std::out_of_range("越界访问");self->data[i] = v;}}%template (intArray40)wrapped_array;%template (doubleArray15)wrapped_array;

诀窍在于我们使用 %extend 来提供 __getitem__ 这是 Python 用于下标读取和 __setitem__ 用于写入.(我们也可以提供一个 __iter__ 来使类型可迭代).我们还提供了特定的 wraped_array 我们希望使用唯一名称使 SWIG 将它们包装在输出中.

使用提供的接口,我们现在可以:

<预><代码>>>>进口测试>>>foo = test.Test()>>>foo.icntl[30] = -654321>>>打印 foo.icntl[30]-654321>>>打印 foo.icntl[40]回溯(最近一次调用最后一次):文件<stdin>",第 1 行,在 <module> 中文件test.py",第 108 行,在 __getitem__ 中def __getitem__(self, *args): return _test.intArray40___getitem__(self, *args)IndexError:越界访问

您可能还会发现这种方法替代.

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?

解决方案

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.

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__ which is what Python uses for subscript reads and __setitem__ for the writes. (We could also have supplied a __iter__ to make the type iteratable). We also gave the specific wraped_arrays 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 useful/interesting as an alternative.

这篇关于结构内部的 SWIG/python 数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆