我在header.h中定义了一个结构,如下所示:
- typedef struct {
- ....
- int icntl[40];
- double cntl[15];
- int *irn,*jcn;
- ....
当我使用这种结构初始化一个对象时,我可以访问整数/双精度但不能访问数组.
- >> 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
如何访问读/写中的值?
解决方法
最简单的方法是将数组包装在一个结构中,然后可以提供
extra methods to meet the “subscriptable” requirements.
我把一个小例子放在一起.它假设你正在使用C,但是等效的C版本从这个构造起来相当简单,它只需要一点点重复.
首先,我们要包装的结构的C头和我们用于包装固定大小数组的模板:
- 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;
我们相应的SWIG界面看起来像:
- %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>;
诀窍是我们使用%extend来提供__getitem__
,这是Python用于下标读取而__setitem__
用于写入. (我们也可以提供__iter__来使类型可迭代).我们还给出了我们想要使用唯一名称的特定wraped_arrays,以使SWIG将它们包装在输出中.
使用提供的界面,我们现在可以:
- >>> 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
您可能还会发现this approach有用/有趣作为替代方案.