如何将结构*自动转换为字典?

时间:2017-12-22 14:51:27

标签: cython

mystruct.pxd

ctypedef struct foo:
    pass

ctypedef struct myStruct:
    int field1
    int field2
    foo* field3

mystruct.pyx

class MyStruct:
    cdef myStruct* _ptr
    def __cinit__(self):
        self._ptr = create_myStruct()
    def __getattr__(self, key):
        if key in self._ptr[0]:
            return self._ptr[0][key]

__getattr__无法使用cython进行编译。 尝试索引非数组类型'myStruct' 删除[0]会导致编译器崩溃。

尝试:

def get_dict(self):
    return self._ptr      # cannot convert 'myStruct *' to Python object
    return self._ptr[0]   # cannot convert 'myStruct' to Python object

这些结构包含许多我需要作为属性访问的字段。编写基本的@property包装器会给文件增加很多混乱,所以我希望能够使用简单的 getaddr 。有什么想法吗?

更新:更改了field3的类型

1 个答案:

答案 0 :(得分:2)

问题似乎是foo* field3,因为foo是一个自定义结构而不是基本类型(数字,char *)自动转换不起作用。似乎没有办法直接解决这个问题。我有两个解决方法:

  1. 当您需要访问子结构时,将field3的类型更改为unsigned int(或任何指针大小)并转换为foo*。这不是一个非常好的解决方法,但如果你的成员真的是不透明的类型而且不是可访问的结构,它就可以正常工作。

  2. 写一些内容以明确转换为字典。

  3. 这就是我最终要做的事情。它是字段名称的另一个重复,但可以使用copy-paste-modify

    轻松创建
    def to_dict(self):
      return {'field1':self._ptr.field1,
              'field2':self._ptr.field2,
              'field3':FooWrapper().from_ptr(self._ptr.field3)  # or an int if opaque
             }
    cdef class FooWrapper:
        cdef foo* _ptr
        def from_ptr(self, ptr):
            assert(ptr is not NULL)
            self._ptr = ptr
            return self