Cython 中 dealloc 中的 Python 对象

问题描述 投票:0回答:1

在文档中写道:“您在 _cinit_() 方法中显式分配(例如,通过 malloc)的任何 C 数据都应该在 _dealloc_() 方法中释放。”

这不是我的情况。我有以下扩展类:

cdef class SomeClass:
    cdef dict data
    cdef void * u_data

    def __init__(self, data_len):
        self.data = {'columns': []}
        if data_len > 0:
            self.data.update({'data': deque(maxlen=data_len)})
        else:
            self.data.update({'data': []})
        self.u_data = <void *>self.data

    @property
    def data(self):
        return self.data

    @data.setter
    def data(self, new_val: dict):
        self.data = new_val

某些 C 函数可以访问此类,并将一些数据附加到 SomeClass().data 字典中。当我想删除 SomeClass() 的实例时,我应该在

__dealloc__
中写什么?

也许类似:

def __dealloc__(self):
    self.data = None
    free(self.u_data)

或者根本不需要释放任何东西?

cython
1个回答
4
投票

不,你不需要,也不应该。来自文档

您需要小心使用

__dealloc__()
方法所做的事情。当你的
__dealloc__()
方法被调用时,该对象可能已经被部分销毁,并且就 Python 而言可能不处于有效状态,因此你应该避免调用任何可能接触该对象的 Python 操作。特别是,不要调用该对象的任何其他方法或执行任何可能导致该对象复活的操作。最好坚持只释放 C 数据。

您无需担心释放对象的 Python 属性,因为这将在您的

__dealloc__()
方法返回后由 Cython 为您完成。


您可以通过检查 C 代码来确认这一点(您需要查看完整的代码,而不仅仅是带注释的 HTML)。有一个自动生成的函数

__pyx_tp_dealloc_9someclass_SomeClass
(名称可能会略有不同,具体取决于您对模块的称呼),可以执行一系列操作,包括:

__pyx_pw_9someclass_9SomeClass_3__dealloc__(o);
/* some other code */
Py_CLEAR(p->data);

其中函数

__pyx_pw_9someclass_9SomeClass_3__dealloc__
是您的用户定义的
__dealloc__
(包装器)。
Py_CLEAR
将确保
data
进行适当的引用计数,然后设置为
NULL

这有点难以理解,因为它都经过了几层包装器,但您可以确认它按照文档所述进行操作。

© www.soinside.com 2019 - 2024. All rights reserved.