是否可以从c++中删除python中分配的对象?
Is it ok to delete object allocated in python from c++?
在我的程序中,我用c++管理对python对象的引用。也就是说,我所有的类都派生自类reference,它包含指向相应python对象的指针。
class Referenced
{
public:
unsigned use_count() const
{
return selfptr->ob_refcnt;
}
void add_ref() const
{
Py_INCREF(selfptr);
}
void remove_ref() const
{
Py_DECREF(selfptr);
}
PyObject* selfptr;
};
我使用intrusive_ptr来保存从reference派生的对象。这使我可以轻松地在c++中保存对所需python对象的引用,并在必要时访问它们。但是当python对象将从c++中删除时,我的程序崩溃(仅在windows中),即当我调用Py_DECREF(selfptr)时,selfptr->ob_refcnt == 1。这个方法可以吗?
Upd:我终于找出了程序中的问题。这与物体移除没有直接关系。为了检查最初的问题,我实现了简单的扩展模块,记住对python对象的引用并根据需要释放它。
#include <Python.h>
static PyObject* myObj;
static PyObject* acquirePythonObject(PyObject* self, PyObject* obj)
{
printf("trying to acquire python object %p, refcount = %dn", obj, obj->ob_refcnt);
myObj = obj;
Py_INCREF(myObj);
printf("reference acquiredn");
return Py_True;
}
static PyObject* freePythonObject(PyObject*, PyObject*)
{
printf("trying to free python object %p, refcount = %dn", myObj, myObj->ob_refcnt);
Py_DECREF(myObj);
printf("reference removedn");
return Py_True;
}
static PyMethodDef moduleMethods[] =
{
{"acquirePythonObject", acquirePythonObject, METH_O, "hold reference to python object."},
{"freePythonObject", freePythonObject, METH_NOARGS, "free reference to python object."},
{NULL, NULL, 0, NULL}
};
PyMODINIT_FUNC initmodule(void)
{
Py_InitModule("module", moduleMethods);
}
和python脚本:
import module
class Foo:
def __init__(self):
print "Foo is created"
def __deinit__(self):
print "Foo is destroyed"
def acquireFoo():
foo = Foo()
module.acquirePythonObject(foo)
def freeFoo():
module.freePythonObject()
if __name__ == "__main__":
acquireFoo()
freeFoo()
示例在windows和linux中无缝运行。输出如下:
Foo is created
trying to acquire python object 0x7fa19fbefd40, refcount = 2
reference acquired
trying to free python object 0x7fa19fbefd40, refcount = 1
Foo is destoryed
reference removed
这个方法可以吗?
基本上,但是…
- 我没有看到任何保证
add_ref
/remove_ref
被调用正确的次数(使用RAII将自动执行此操作-也许这就是你的intrusive_ptr所做的?) - 如果你做尝试
remove_ref
太多次,我不确定Python保证什么。如果您在知道计数从1到> 0的情况下设置selfptr = NULL
,您可能会发现这个问题- 要么硬崩溃,要么显式检查,要么使用
Py_XDECREF
- 更好,用
Py_CLEAR
代替
- 要么硬崩溃,要么显式检查,要么使用
最后……你有任何崩溃转储或诊断信息吗?
相关文章:
- 使用操作重载对象重新分配对象
- 静态分配对象的值初始化
- C++ 将抽象类型的动态分配对象传递给函数并存储在向量中
- 堆分配对象中的堆栈对象在 c++ 中在哪里分配?
- 在 c++ 的构造函数中分配对象向量时出错
- 动态分配对象中的字段-动态分配更好还是静态分配更好?C++
- 操作后通过运算符分配对象
- 如何捕获源自静态分配对象的构造函数的异常?
- 在C++中,当重新分配对象时,为什么构造函数在析构函数之前触发?
- 如何使用每个对象的单个构造函数参数动态分配C++对象数组?
- 将动态分配对象传递到 boost::any 构造函数中
- 混合指向已分配对象和作用域对象的指针
- C 删除指向动态分配对象的指针
- 有关动态分配对象的问题
- 类的堆分配对象是否在其作用域之后但在 C++ 中调用其析构函数之前处于活动状态
- C++ 中的黑白堆分配对象和堆栈分配对象的性能差异
- 是隐式创建的默认构造函数,负责分配对象内存
- 如何删除用于动态分配对象的智能指针
- 分配对象数组时如何初始化每个对象
- 用于堆栈分配对象的C++虚拟析构函数内联