如何将结构指针传递给 Cython 的 cdef class 的 __cinit__
How to pass struct pointer to __cinit__ of Cython's cdef class
我正在尝试使用必须使用 cdef 结构指针的 cinit 来实现 cdef class。
C 头
typedef struct foo *FOO;
PXD 文件:
extern ...:
cdef struct foo
ctypedef foo *FOO
PYX 文件:
cdef class ClassX(object):
def __cinit__(self, FOO arg):
...
Cython 编译器说 "Cannot convert Python object argument to type 'FOO'"。有什么问题以及如何将结构指针传递给 cinit?
看来我发现了类似的问题:how to cython class function's parameter accept c++ struct。简短回答:无法将 C 结构传递给 Python (def) 函数。我必须将结构包装到 Python 对象中。
以下是我为我的案例设法解决的一些方法,它们非常具体。
方法 1 - 将指针转换为 uint64 数字(有点脏)
您必须确保引用在复制之前未被删除,但首先将您的结构指针转换为无符号的 64 位数字,然后强制转换并可能取消引用返回您的对象。像这样
from cython.operator cimport dereference as deref
ctypedef unsigned long long uint64_t
...
cdef class SomeClass(object):
cdef FooStruct foo
def __cinit__(self, uint64_t arg):
self.foo = deref(<FooStruct*> arg) # preferably copy over keeping pointer
然后构建它
cdef FooStruct yourfoo = ... # your struct
cdef SomeClass res
res = SomeClass(<uint64_t> &yourfoo)
这不是最漂亮的解决方案,但它适用于特定情况。
方法二 - 同样的PYX文件赋值函数(首选)
我发现此方法仅适用于同一 PYX 文件中的对象引用。因此,如果您使用 setter 函数定义 cdef class
来复制数据,而不暴露给 python,那么您可以更新内部结构。
cdef class SomeClass(object):
cdef FooStruct foo
def __cinit__(self):
...
cdef void _set(self, FooStruct &data):
self.foo = data # copy
现在构建它是两条线
cdef FooStruct yourfoo = ... # your struct
cdef SomeClass res
res = SomeClass()
res._set(yourfoo)
我正在尝试使用必须使用 cdef 结构指针的 cinit 来实现 cdef class。
C 头
typedef struct foo *FOO;
PXD 文件:
extern ...:
cdef struct foo
ctypedef foo *FOO
PYX 文件:
cdef class ClassX(object):
def __cinit__(self, FOO arg):
...
Cython 编译器说 "Cannot convert Python object argument to type 'FOO'"。有什么问题以及如何将结构指针传递给 cinit?
看来我发现了类似的问题:how to cython class function's parameter accept c++ struct。简短回答:无法将 C 结构传递给 Python (def) 函数。我必须将结构包装到 Python 对象中。
以下是我为我的案例设法解决的一些方法,它们非常具体。
方法 1 - 将指针转换为 uint64 数字(有点脏) 您必须确保引用在复制之前未被删除,但首先将您的结构指针转换为无符号的 64 位数字,然后强制转换并可能取消引用返回您的对象。像这样
from cython.operator cimport dereference as deref
ctypedef unsigned long long uint64_t
...
cdef class SomeClass(object):
cdef FooStruct foo
def __cinit__(self, uint64_t arg):
self.foo = deref(<FooStruct*> arg) # preferably copy over keeping pointer
然后构建它
cdef FooStruct yourfoo = ... # your struct
cdef SomeClass res
res = SomeClass(<uint64_t> &yourfoo)
这不是最漂亮的解决方案,但它适用于特定情况。
方法二 - 同样的PYX文件赋值函数(首选)
我发现此方法仅适用于同一 PYX 文件中的对象引用。因此,如果您使用 setter 函数定义 cdef class
来复制数据,而不暴露给 python,那么您可以更新内部结构。
cdef class SomeClass(object):
cdef FooStruct foo
def __cinit__(self):
...
cdef void _set(self, FooStruct &data):
self.foo = data # copy
现在构建它是两条线
cdef FooStruct yourfoo = ... # your struct
cdef SomeClass res
res = SomeClass()
res._set(yourfoo)