Accessing an array of nested structure in python using SWIG

I was not able to figure out how to access the elements of the SubStatus array in the following nested structure. I seem to see the first element, but I don’t understand how to get indexing, for example, as a list.

Any help is greatly 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" 
+2
source share
1 answer

You can wrap this header without changing it, buying 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 changing the header to use wrapped_array , we used %ignore to tell SWIG we will provide our own definition of STATUS to wrap it. (This is completely legal; the created SWIG shell will still use the real definition from status.h)

We insert into this modified definition a getSubStatus() , which returns an object that acts as a proxy for the real array in STATUS . This proxy, in turn, provides __getitem__ , __setitem__ and __len__ , which python is looking for to use the index operator.

There may be a way to do this correctly in Python without requiring getSubStatus() by making SWIG set __swig_setmethods__["SubStatus"] and __swig_getmethods__["SubStatus"] appropriately, but I'm not sure if I can make python SWIG do this.

If you are using C but not using C ++, you need to drop the pattern in favor of a simple struct and use a pointer instead of an array reference.

+1
source

Source: https://habr.com/ru/post/1439024/


All Articles