Cython:使用原始指针重载构造函数初始化

我试图包装两个C ++类:Cluster和ClusterTree。 ClusterTree有一个方法get_current_cluster(),用于实例化一个Cluster对象,并返回对其的引用。 ClusterTree拥有Cluster对象,并在C ++中管理其创建和删除。

我用cython包装了Cluster,导致了PyCluster。

PyCluster应该有两种创建方式:

1)通过传入两个数组,这意味着Python应该自动处理删除(通过__dealloc__)
2)直接传入一个原始C ++指针(由ClusterTree的get_current_cluster()创建)。 在这种情况下,ClusterTree会承担删除底层指针的责任。

from libcpp cimport bool
from libcpp.vector cimport vector

cdef extern from "../include/Cluster.h" namespace "Terran":
    cdef cppclass Cluster:
        Cluster(vector[vector[double]],vector[int]) except +

cdef class PyCluster:
    cdef Cluster* __thisptr
    __autoDelete = True

    def __cinit__(self, vector[vector[double]] data, vector[int] period):
        self.__thisptr = new Cluster(data, period)  

    @classmethod
    def __constructFromRawPointer(self, raw_ptr):
        self.__thisptr = raw_ptr
        self.__autoDelete = False

    def __dealloc__(self):
        if self.__autoDelete:
            del self.__thisptr

cdef extern from "../include/ClusterTree.h" namespace "Terran":
    cdef cppclass ClusterTree:
        ClusterTree(vector[vector[double]],vector[int]) except +
        Cluster& getCurrentCluster()

cdef class PyClusterTree:

    cdef ClusterTree *__thisptr

    def __cinit__(self, vector[vector[double]] data, vector[int] period):
        self.__thisptr = new ClusterTree(data,period)

    def __dealloc__(self):
        del self.__thisptr

    def get_current_cluster(self):

        cdef Cluster* ptr = &(self.__thisptr.getCurrentCluster())
        return PyCluster.__constructFromRawPointer(ptr)

这导致:

Error compiling Cython file:
------------------------------------------------------------
...
    def get_current_cluster(self):
        cdef Cluster* ptr = &(self.__thisptr.getCurrentCluster())
        return PyCluster.__constructFromRawPointer(ptr)
                                                     ^
------------------------------------------------------------

terran.pyx:111:54: Cannot convert 'Cluster *' to Python object

注意我不能cdef __init__或@classmethods。


指针只能作为参数传递给cdef'd函数,并且cinit必须被定义。 但提供一个classmethod 几乎是一种方式!

cdef Cluster* __thisptr
cdef bool __wrapped  ## defaults to False

@staticmethod
cdef PyCluster wrap(Cluster* ptr):
    cdef PyCluster pc = PyCluster([], [])  ## Initialize as cheaply as possible
    del pc.__thisptr  ## delete the old pointer to avoid memory leaks!
    pc.__thisptr = ptr
    pc.__wrapped = True
    return pc

我知道这是一个古老的问题,但是在我最近与Cython斗争之后,我想我会为了后代发表一个答案。

在我看来,你可以使用复制构造函数从现有的Cluster对象中创建一个新的PyCluster对象。

在C代码中定义复制构造函数,然后使用new调用Python类定义中的复制构造函数(在这种情况下,当指针传递时)。 这将起作用,但它可能不是最好或最高性能的解决方案。

链接地址: http://www.djcxy.com/p/87925.html

上一篇: Cython: overloaded constructor initialization using raw pointer

下一篇: Declaring numpy array and c pointer in cython