我在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
如何访问读/写中的值?
答案 0 :(得分:6)
最简单的方法是将数组包装在struct
内,然后提供extra methods to meet the "subscriptable" requirements。
我把一个小例子放在一起。它假设你正在使用C ++,但是等效的C版本从这个构造起来相当简单,它只需要一点点重复。
首先,我们要包装的包含struct
的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_array
来使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有用/有趣。
答案 1 :(得分:3)
我会在python
中完成此操作ptr = int(st.icntl)
import ctypes
icntl = ctypes.c_int * 40
icntl = icntl.from_address(ptr)
print icntl[0]
icntl[0] = 1
for i in icntl:
print i
答案 2 :(得分:0)
您考虑过使用SWIG卡瑞吗?
在您的头文件中:
typedef struct {
int icntl[40];
double cntl[15];
} some_struct_t;
然后,在您的Swig文件中:
%module example
%include "carrays.i"
// ...
%array_class(int, intArray);
%array_class(double, doubleArray);
Python看起来像这样:
icntl = example.intArray(40)
cntl = example.doubleArray(15)
for i in range(0, 40):
icntl[i] = i
for i in range(0, 15):
cntl[i] = i
st = example.some_struct_t()
st.icntl = icntl
st.cntl = cntl
您仍然不能直接设置结构。我写了python包装器代码来隐藏样板。
array_class仅适用于基本类型(int,double),如果您需要其他类型(例如uint8_t),则需要使用具有更多样板的array_functions,但它们可以工作。
http://www.swig.org/Doc3.0/SWIGDocumentation.html#Library_carrays