{tp_alloc,tp_dealloc}和{tp_new,tp_free}应该被视为对吗? [英] Should {tp_alloc, tp_dealloc} and {tp_new, tp_free} be considered as pairs?
问题描述
是否确实应该在tp_dealloc中销毁在tp_alloc中创建的任何内容?同样适用于{tp_new,tp_free}吗?
Is it true that whatever is created in tp_alloc should be destroyed in tp_dealloc? And similarly for {tp_new, tp_free}?
它看起来很明显是对称的,但请您澄清一下.
It looks like an obvious symmetry, but I would be grateful for clarification.
我的实际用例是这样的: 我有:
My actual use case is this: I have:
class OSClass : PyObject {...}
class Final : OSClass {...}
因此对应的PyTypeObject pto
具有:
pto->tp_basicsize = sizeof(FinalClass)
pto->tp_dealloc = (destructor)
[](PyObject* pyob) { PyMem_Free(pyob); };
但是,新样式类将PyObject及其对应的C ++对象彼此分开存储,因此工作方式不同.
However the new style class stores the PyObject and its corresponding C++ object separately from one another, and therefore works differently.
它将在tp_new中创建PyObject,并在tp_init中创建相应的C ++对象.
It creates the PyObject in tp_new, and the corresponding C++ object in tp_init.
并在tp_dealloc中销毁它们两者
And destroys both of them in tp_dealloc
这是正确/最佳吗?
代码:
// extra void* to point to corresponding C++ object
pto->tp_basicsize = sizeof(PyObject) + sizeof(void*)
pto->tp_new = new_func;
pto->tp_init = init_func;
pto->tp_dealloc = dealloc_func;
static PyObject* new_func( PyTypeObject* subtype, PyObject* args, PyObject* kwds )
{
// First we create the Python object.
// The type-object's tp_basicsize is set to sizeof(Bridge)
// (Note: We could maybe use PyType_GenericNew for this:
// http://stackoverflow.com/questions/573275/python-c-api-object-allocation )
//
PyObject* pyob = subtype->tp_alloc(subtype,0);
Bridge* bridge = reinterpret_cast<Bridge*>(pyob);
// We construct the C++ object later in init_func (below)
bridge->m_pycxx_object = nullptr;
return pyob;
}
static int init_func( PyObject* self, PyObject* args, PyObject* kwds )
{
try
{
Object a = to_tuple(args);
Object k = to_dict(kwds);
Bridge* bridge{ reinterpret_cast<Bridge*>(self) };
// NOTE: observe this is where we invoke the
// constructor, but indirectly (i.e. through final)
bridge->m_pycxx_object = new FinalClass{ bridge, a, k };
}
catch( Exception & )
{
return -1;
}
return 0;
}
static void dealloc_func( PyObject* pyob )
{
auto final = static_cast<FinalClass*>( cxxbase_for(pyob) );
delete final;
PyMem_Free(pyob);
COUT( "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" );
//self->ob_type->tp_free(self);
}
推荐答案
来自 tp_new
文档,您拥有
From the tp_new
documentation you have
tp_new 函数应调用
subtype->tp_alloc(subtype, nitems)
为对象分配空间,然后仅在绝对必要的情况下进行更多的初始化.可以安全地忽略或重复的初始化应该放在 tp_init 处理程序中.一个好的经验法则是,对于不可变类型,所有初始化都应在 tp_new 中进行,而对于可变类型,大多数初始化应推迟至 tp_init .
The tp_new function should call
subtype->tp_alloc(subtype, nitems)
to allocate space for the object, and then do only as much further initialization as is absolutely necessary. Initialization that can safely be ignored or repeated should be placed in the tp_init handler. A good rule of thumb is that for immutable types, all initialization should take place in tp_new, while for mutable types, most initialization should be deferred to tp_init.
这就是为什么要在tp_new
中创建对象本身并在tp_init
中对其进行初始化的原因.创建C ++对象是初始化的一部分.由于 tp_init
文档声明>
That's why you create the object itself in tp_new
and initialise it in tp_init
. Creating the C++ object is part of the initialisation. Since the tp_init
documentation states
此函数对应于类的 __ init __ ()方法.像 __ init __ ()一样,可以在不调用 __ init __ ()的情况下创建实例,并且可以通过调用实例的 __ init __ 重新初始化实例.再次>()方法.
This function corresponds to the __init__() method of classes. Like __init__(), it is possible to create an instance without calling __init__(), and it is possible to reinitialize an instance by calling its __init__() method again.
您需要检查bridge->m_pycxx_object != nullptr
,并在出现故障时删除已初始化的实例或引发错误.
You need to check for bridge->m_pycxx_object != nullptr
and delete the already initialised instance on failure or raise an error.
然后在tp_dealloc
中销毁Python对象.由于C ++对象是该对象的一部分,因此也需要在该对象中销毁该对象.
In tp_dealloc
you then destroy the Python object. Since the C++ object is part of this one, it needs to be destroyed there as well.
返回配对:您在tp_new
中调用tp_alloc
,在tp_dealloc
中调用tp_free
.因此{tp_alloc
,tp_free
}和{tp_new
,tp_dealloc
}应该被视为对.
Back to the pairing: You call tp_alloc
within tp_new
and tp_free
within tp_dealloc
. So {tp_alloc
, tp_free
} and {tp_new
, tp_dealloc
} should be considered as pairs.
这篇关于{tp_alloc,tp_dealloc}和{tp_new,tp_free}应该被视为对吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!