Python 如何编写封装预分配数据的扩展类型?

Python 如何编写封装预分配数据的扩展类型?,python,c,cython,Python,C,Cython,我有一些已经分配和初始化的结构中的数据。 我可以保证,在这些对象的任何生存期内,数据都不会被释放。如何用Cython将其包装到Python对象中?以下内容不起作用,但我希望它能解释我的意图: from libc.stdlib cimport malloc ctypedef struct Point: int x int y cdef class _MyWrapper: cdef Point* foo def __cinit__(self, Point* foo

我有一些已经分配和初始化的结构中的数据。 我可以保证,在这些对象的任何生存期内,数据都不会被释放。如何用Cython将其包装到Python对象中?以下内容不起作用,但我希望它能解释我的意图:

from libc.stdlib cimport malloc

ctypedef struct Point:
    int x
    int y

cdef class _MyWrapper:
    cdef Point* foo
    def __cinit__(self, Point* foo):
        self.foo = foo

def create_eternal_MyWrapper(int x, int y):
    cdef Point* p
    p = <Point*>malloc(sizeof(Point))
    p.x = x
    p.y = y
    return _MyWrapper(p)
来自libc.stdlib cimport malloc
ctypedef结构点:
整数x
智力
cdef类\u MyWrapper:
cdef点*foo
定义(自我,点*foo):
self.foo=foo
def create_external_MyWrapper(整数x,整数y):
cdef点*p
p=malloc(sizeof(点))
p、 x=x
p、 y=y
返回_MyWrapper(p)
在此服务器上运行cython的输出:

Error compiling Cython file:
------------------------------------------------------------
...
def create_eternal_MyWrapper(int x, int y):
    cdef Point* p
    p = <Point*>malloc(sizeof(Point))
    p.x = x
    p.y = y
    return _MyWrapper(p)
                      ^
------------------------------------------------------------

examplecy.pyx:17:23: Cannot convert 'Point *' to Python object
编译Cython文件时出错: ------------------------------------------------------------ ... def create\u永恒\u MyWrapper(int x,int y): cdef点*p p=malloc(sizeof(点)) p、 x=x p、 y=y 返回_MyWrapper(p) ^ ------------------------------------------------------------ pyx:17:23:无法将“点*”转换为Python对象 如前所述,
方法都使用
PyObject\u调用
API函数,该函数只能接受PyObject类型的参数。因此,正如中所建议的,您应该在全局工厂方法内初始化C属性:

from libc.stdlib cimport malloc

ctypedef struct Point:
    int x
    int y

cdef class _MyWrapper:
    cdef Point* fooless
    def __init__(self, *args, **kwargs):
        raise TypeError("This class cannot be instantiated from Python")

cpdef _MyWrapper create_MyWrapper(int x, int y):
    cdef _MyWrapper w = _MyWrapper.__new__(_MyWrapper)

    cdef Point* p
    p = <Point*>malloc(sizeof(Point))
    p.x = x
    p.y = y

    w.foo = p

    # initialize all other fields explicitly
    # ...

    return w
来自libc.stdlib cimport malloc
ctypedef结构点:
整数x
智力
cdef类\u MyWrapper:
cdef点*愚蠢
定义初始化(self,*args,**kwargs):
raise TypeError(“无法从Python实例化此类”)
cpdef_MyWrapper create_MyWrapper(int x,int y):
cdef\u MyWrapper w=\u MyWrapper.\u新的\u(\u MyWrapper)
cdef点*p
p=malloc(sizeof(点))
p、 x=x
p、 y=y
w、 foo=p
#显式初始化所有其他字段
# ...
返回w
当然可以在
\u MyWrapper
本身中创建一个专用的初始化方法,但我认为这是相当不安全的,因为在类实例化之后,用户可能会忘记调用此类方法


PS:如果有一个更简单的解决方案,我会很高兴的

什么是
MyAllocatedData
?C结构?A
cdef类
?一种Python对象?一种C类型。具体来说,是一个结构。你想要C和Cython中的确切结构定义吗?我认为这些细节无关紧要。但它如何“不起作用”?你能举个例子吗?@delnan这很公平,对不起。我现在给出了一个完整的例子,问题不在于分配数据的方式,而在于将指针传递给构造函数的方式。传递空指针将导致相同的错误