SWIG / python数组内部结构

前端之家收集整理的这篇文章主要介绍了SWIG / python数组内部结构前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我在header.h中定义了一个结构,如下所示:
  1. typedef struct {
  2. ....
  3. int icntl[40];
  4. double cntl[15];
  5. int *irn,*jcn;
  6. ....

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

  1. >> st.icntl
  2. <Swig Object of type 'int *' at 0x103ce37e0>
  3. >> st.icntl[0]
  4. Traceback (most recent call last):
  5. File "test_mumps.py",line 19,in <module>
  6. print s.icntl[0]
  7. TypeError: 'SwigPyObject' object is not subscriptable

如何访问读/写中的值?

解决方法

最简单的方法是将数组包装在一个结构中,然后可以提供 extra methods to meet the “subscriptable” requirements.

我把一个小例子放在一起.它假设你正在使用C,但是等效的C版本从这个构造起来相当简单,它只需要一点点重复.

首先,我们要包装的结构的C头和我们用于包装固定大小数组的模板:

  1. template <typename Type,size_t N>
  2. struct wrapped_array {
  3. Type data[N];
  4. };
  5.  
  6. typedef struct {
  7. wrapped_array<int,40> icntl;
  8. wrapped_array<double,15> cntl;
  9. int *irn,*jcn;
  10. } Test;

我们相应的SWIG界面看起来像:

  1. %module test
  2.  
  3. %{
  4. #include "test.h"
  5. #include <exception>
  6. %}
  7.  
  8. %include "test.h"
  9. %include "std_except.i"
  10.  
  11. %extend wrapped_array {
  12. inline size_t __len__() const { return N; }
  13.  
  14. inline const Type& __getitem__(size_t i) const throw(std::out_of_range) {
  15. if (i >= N || i < 0)
  16. throw std::out_of_range("out of bounds access");
  17. return self->data[i];
  18. }
  19.  
  20. inline void __setitem__(size_t i,const Type& v) throw(std::out_of_range) {
  21. if (i >= N || i < 0)
  22. throw std::out_of_range("out of bounds access");
  23. self->data[i] = v;
  24. }
  25. }
  26.  
  27. %template (intArray40) wrapped_array<int,40>;
  28. %template (doubleArray15) wrapped_array<double,15>;

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

使用提供的界面,我们现在可以:

  1. >>> import test
  2. >>> foo = test.Test()
  3. >>> foo.icntl[30] = -654321
  4. >>> print foo.icntl[30]
  5. -654321
  6. >>> print foo.icntl[40]
  7. Traceback (most recent call last):
  8. File "<stdin>",line 1,in <module>
  9. File "test.py",line 108,in __getitem__
  10. def __getitem__(self,*args): return _test.intArray40___getitem__(self,*args)
  11. IndexError: out of bounds access

您可能还会发现this approach有用/有趣作为替代方案.

猜你在找的Python相关文章