gpt4 book ai didi

c++ - {tp_alloc, tp_dealloc} 和 {tp_new, tp_free} 应该被视为成对吗?

转载 作者:搜寻专家 更新时间:2023-10-31 02:24:15 26 4
gpt4 key购买 nike

在 tp_alloc 中创建的任何东西都应该在 tp_dealloc 中销毁,这是真的吗?对于 {tp_new, tp_free} 也是如此吗?

它看起来很明显是对称的,但我将不胜感激。


我的实际用例是这样的:我有:

class OSClass : PyObject {...}

class Final : OSClass {...}

所以相应的PyTypeObject pto有:

pto->tp_basicsize = sizeof(FinalClass)
pto->tp_dealloc = (destructor)
[](PyObject* pyob) { PyMem_Free(pyob); };

然而,新样式类将 PyObject 及其对应的 C++ 对象彼此分开存储,因此工作方式不同。

它在 tp_new 中创建 PyObject,并在 tp_init 中创建相应的 C++ 对象。

并在 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 documentation你有

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 documentation

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 并在失败或引发错误时删除已初始化的实例。

然后在 tp_dealloc 中销毁 Python 对象。由于 C++ 对象是此对象的一部分,因此也需要在那里销毁它。


回到配对:您在 tp_new 中调用 tp_alloc,在 tp_dealloc 中调用 tp_free。所以 {tp_alloc, tp_free} 和 {tp_new, tp_dealloc} 应该被认为是成对的。

关于c++ - {tp_alloc, tp_dealloc} 和 {tp_new, tp_free} 应该被视为成对吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28263177/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com