【问题标题】:nested structure array access in python using SWIG使用 SWIG 在 python 中访问嵌套结构数组
【发布时间】:2011-10-10 13:15:45
【问题描述】:

我无法弄清楚如何访问以下嵌套结构中的数组元素 SubStatus。我似乎确实能够看到第一个元素,但不明白如何强制索引,例如,作为列表。

非常感谢任何帮助。

status.h:

// Data Types
typedef char           CHAR;   // 8 bits signed
typedef short          SHORT;  // 16 bits signed
typedef long           LONG;   // 32 bits signed
typedef unsigned char  UCHAR;  // 8 bits unsigned
typedef unsigned short USHORT; // 16 bits usigned

#define FUNC_TYPE       // built in C, leave reference as C
#define DLL_API extern FUNC_TYPE __declspec(dllimport)

// Sub Status Data
typedef struct
{
    LONG  xyz;                              
    LONG  abc;                                           
} SUB_STATUS;


// Status Info
typedef struct
{
    UCHAR  qrs;             
    UCHAR  tuv;             
    SUB_STATUS SubStatus[4];     
    LONG   wxy;     
} STATUS;

DLL_API  SHORT  GetStatus( STATUS *Status );

status.i

%module status
 %{
 /* Includes the header in the wrapper code */
 #include "status.h"
 %}

 /* Parse the header file to generate wrappers */
 %include "windows.i"
 %include "typemaps.i" 
 %include "status.h"

【问题讨论】:

  • 感谢 awoodland,但我无法控制 .h 文件,因为它来自供应商的发行版。如果我正确理解了其他解决方案,我必须对 c 源代码进行修改,对吗?我希望得到一个只会影响 .i 文件的答案。
  • 您可以在不修改标题的情况下应用它,但它有点棘手。希望稍后我会整理一个示例。

标签: python arrays structure swig


【解决方案1】:

您可以包装此标头而无需修改它购买类似:

%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"

这与my answer here 基本相同,但我们没有修改标头以使用wrapped_array,而是使用%ignore 告诉SWIG 我们将提供我们自己的STATUS 定义以对其进行包装. (这是完全合法的,SWIG 生成的包装器仍将使用 status.h 中的真实定义)

我们将getSubStatus() 注入到这个改变的定义中,它返回一个对象,该对象充当STATUS 中真实数组的代理。该代理依次提供__getitem____setitem____len__,python 寻找使用下标运算符。

可能有一种方法可以在 Python 中正确执行此操作,而无需 getSubStatus(),使 SWIG 正确设置 __swig_setmethods__["SubStatus"]__swig_getmethods__["SubStatus"],但我不确定如何制作 SWIG python这样做。

如果您使用的是 C,而不是 C++,则需要删除模板,而只使用普通的 struct,并使用指针而不是对数组的引用。

【讨论】:

  • Flexo,我正在尝试用 python/swig 做类似的事情,但就我而言,我想使用 C。所以我做了一些类似于 Lou K 的代码但使用了一个玩具结构,typdef struct { int i; int ai[10]; } mystruct;我试图用typdef struct { int data[10]; } wrapped_array_int_10;wrapped_array_int_10* getai() 覆盖ai。我编译了代码,但是从 python 尝试o = example.mystruct() 时,我得到了 mystruct 没有构造函数的错误。你能告诉我我错过了什么吗?谢谢...
  • @yos 你是用 C 还是 C++ 构建的?
  • 我正在用 c 构建。
猜你喜欢
  • 2021-11-30
  • 1970-01-01
  • 2017-02-19
  • 1970-01-01
  • 2023-03-17
  • 2021-05-21
  • 2011-12-28
相关资源
最近更新 更多