删除对象时无法调用 __dealloc__

Gau*_*lio 2 c++ python destructor cython

我有以下 C++ 类:

。H

class ALabSet: public LabSet {
public:
    PyObject *m_obj;

    ALabSet(PyObject *obj);

    virtual ~ALabSet();

    PyObject *GetPyObj();

};
Run Code Online (Sandbox Code Playgroud)

.CPP

ALabSet::ALabSet(PyObject *obj): LabSet() {

    this->m_obj = obj;
    // Provided by "cyelp_api.h"
    if (import_cyelp()) {
    } else {
        Py_XINCREF(this->m_obj);
    }

}


ALabSet::~ALabSet() {
    Py_XDECREF(this->m_obj);
}


PyObject *ALabSet::GetPyObj() {
    return this->m_obj;
}
Run Code Online (Sandbox Code Playgroud)

我用 Cython 将其暴露如下:

cdef extern from "adapter/ALabSiteSetsManager.h" namespace "elps" :
    cdef cppclass ALabSet:
        ALabSet(PyObject *)

        PyObject *GetPyObj()



cdef class PyLabSet:
    cdef ALabSet *thisptr

    def __cinit__(self):
       self.thisptr = new ALabSet(<PyObject *>self)

    def __dealloc__(self):
       print "delete from PY !"
       if self.thisptr:
           del self.thisptr
Run Code Online (Sandbox Code Playgroud)

我的问题是我不知道如何从 Python 调用析构函数。以下完全不执行任何操作:

a_set = PyLabSet()
del a_set
Run Code Online (Sandbox Code Playgroud)

我在网上找不到类似的问题。你们中有人知道我在这里遇到的情况吗?

我错过了一些关于引用计数管理的东西,或者......

多谢

小智 5

del a_set删除对该对象(局部变量)的引用。在 C++ 对象中还有另一个引用。这称为引用循环。循环 GC可以在一段时间后收集这些信息。但是,无法保证何时(或即使发生这种情况,因此您不应依赖它1

\n\n

例如,包含具有__del__特殊方法的纯 Python 对象的引用循环被记录为根本不会被释放:

\n\n
\n

在版本 3.4 中进行了更改:在 PEP 442 之后,具有__del__()方法 don\xe2\x80\x99t 的对象不再出现gc.garbage

\n
\n\n

我不知道Cython 的实现__dealloc__是否会触发此行为,但如前所述,破坏无论如何都不是确定性的。如果你想释放一些资源(例如,不是 Python 对象的内存块、文件、连接、锁等),你应该公开手动执行此操作的显式方法(参见close方法对象)。上下文管理器可以简化执行此操作的客户端代码。

\n\n

免责声明:几乎所有这些都是特定于 CPython 的。

\n\n

1有些人更喜欢将 GC 视为模拟无限内存可用性的抽象,而不是销毁无法访问的对象。通过这种方法,很明显破坏不是确定性的,甚至不能保证。

\n