Skip to main content
 首页 » 编程设计

python之使用 SWIG 在 python 中访问嵌套结构数组

2025年05月04日8me-sa

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

非常感谢任何帮助。

状态.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 ); 

状态.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" 

请您参考如下方法:

你可以包装这个标题而不必修改它购买做这样的事情:

%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基本相同,但我们没有修改 header 以使用 wrapped_array,而是使用 %ignore 告诉 SWIG 我们将提供我们自己的 STATUS 定义让它包裹起来。 (这是完全合法的,SWIG 生成的包装器仍将使用 status.h 中的真实定义)

我们在这个改变后的定义中注入(inject)一个 getSubStatus(),它返回一个对象,作为 STATUS 中真实数组的代理。该代理依次提供 python 查找以使用下标运算符的 __getitem__、__setitem__ 和 __len__。

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

如果您使用的是 C,而不是 C++,您将希望放弃模板而只使用普通的 struct 并使用指针而不是对数组的引用。