【问题标题】:Cython: overloaded constructor initialization using raw pointer [duplicate]Cython:使用原始指针重载构造函数初始化
【发布时间】:2013-10-14 22:20:36
【问题描述】:

我正在尝试包装两个 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。

【问题讨论】:

  • 你调用的函数必须是cdef。如果 Cython 不支持 cdef classmethod,那么您将需要使用 classmethod 以外的其他内容。
  • 另外,您的类方法尝试修改__thisptr,这是一个实例变量,而不是类变量。由于这个原因,类方法的第一个参数通常是cls,而不是self
  • 不是 cdef 的变量总是实例变量吗?我以为 cdef Cluster* __thisptr;将 __thisptr 声明为实例变量。 @classmethods 不允许修改实例变量吗?
  • 类方法不能修改实例变量;他们甚至无法访问实例(只有类)。

标签: python cython


【解决方案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

【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

      猜你喜欢
      • 2023-03-12
      • 2019-12-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-05
      • 2020-03-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多