0

我正在尝试包装两个 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 然后承担删除底层指针的责任。

从 libcpp cimport 布尔
从 libcpp.vector cimport 向量

cdef extern 来自 "../include/Cluster.h" 命名空间 "Terran":
    cdef cppclass 集群:
        簇(向量[向量[双]],向量[整数])除了+

cdef 类 PyCluster:
    cdef 集群* __thisptr
    __autoDelete = 真

    def __cinit__(self, vector[vector[double]] data, vector[int] period):
        self.__thisptr = 新集群(数据,周期)  

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

    def __dealloc__(self):
        如果自我.__autoDelete:
            德尔自我.__thisptr

cdef extern 来自 "../include/ClusterTree.h" 命名空间 "Terran":
    cdef cppclass ClusterTree:
        ClusterTree(vector[vector[double]],vector[int]) 除了 +
        集群&getCurrentCluster()

cdef 类 PyClusterTree:

    cdef ClusterTree *__thisptr

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

    def __dealloc__(self):
        德尔自我.__thisptr

    def get_current_cluster(self):

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

这导致:

编译 Cython 文件时出错:
-------------------------------------------------- ----------
...
    def get_current_cluster(self):
        cdef Cluster* ptr = &(self.__thisptr.getCurrentCluster())
        返回 PyCluster.__constructFromRawPointer(ptr)
                                                     ^
-------------------------------------------------- ----------

terran.pyx:111:54:无法将“集群 *”转换为 Python 对象

注意我不能 cdef __init__ 或 @classmethods。

4

2 回答 2

1

指针只能作为参数传递给 cdef'd 函数,并且 cinit 必须是 def'd。但是提供一个类方法几乎是要走的路!

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
于 2018-05-08T08:47:10.770 回答
0

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

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

在 C 代码中定义复制构造函数,然后使用new. 这将起作用,尽管它可能不是最好或最高效的解决方案。

于 2015-03-11T07:47:05.887 回答