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

发布于 2024-12-09 10:49:23 字数 1117 浏览 0 评论 0原文

我无法弄清楚如何访问以下嵌套结构中的数组元素 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"

I haven't been able to figure out how to access the array elements SubStatus in the following nested structure. I do seem to be able to see the first element, but don't understand how to force indexing, e.g., as a list.

Any help is much appreciated.

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"

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

断桥再见 2024-12-16 10:49:23

您可以包装此标头,而无需修改它,购买执行以下操作:

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

这基本上与我在这里的答案相同,但是我们没有修改标头以使用 wrapped_array,而是使用 %ignore 告诉 SWIG 我们将为它提供我们自己的 STATUS 定义包裹。 (这是完全合法的,SWIG 生成的包装器仍将使用 status.h 中的真实定义)

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

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

如果您使用的是 C,而不是 C++,您将需要放弃模板而只使用简单的 struct 并使用指针而不是对数组的引用。

You can wrap this header without having to modify it buy doing something like:

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

This is basically the same as my answer here, but instead of modifying the header to use the wrapped_array, we've used %ignore to tell SWIG we will supply our own definition of STATUS for it to wrap. (This is perfectly legal, the SWIG generated wrapper will still use the real definition from status.h)

We inject into this altered definition a getSubStatus(), which returns an object that acts as a proxy to the real array in STATUS. This proxy in turn supplies __getitem__, __setitem__ and __len__ that python looks for to use the subscript operator.

There might be a way to do this properly in Python without needing the getSubStatus(), making SWIG set __swig_setmethods__["SubStatus"] and __swig_getmethods__["SubStatus"] appropriately, but I'm not sure off the top of my head how to make SWIG python do that.

If you're using C, not using C++ you'll want to drop the template in favour of just a plain struct and use a pointer instead of a reference to an array.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文