P i*_*P i 4 c++ pycxx python-c-api
在 tp_alloc 中创建的任何东西都应该在 tp_dealloc 中销毁是真的吗?{tp_new, tp_free} 也是如此?
它看起来像一个明显的对称,但我会很感激澄清。
我的实际用例是这样的:我有:
class OSClass : PyObject {...}
class Final : OSClass {...}
Run Code Online (Sandbox Code Playgroud)
所以对应的PyTypeObject pto有:
pto->tp_basicsize = sizeof(FinalClass)
pto->tp_dealloc = (destructor)
[](PyObject* pyob) { PyMem_Free(pyob); };
Run Code Online (Sandbox Code Playgroud)
然而,新样式类将 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);
}
Run Code Online (Sandbox Code Playgroud)
从您拥有的tp_new文档中
该tp_new函数应该调用
subtype->tp_alloc(subtype, nitems)为对象分配空间,然后只能做尽可能多的进一步初始化为是绝对必要的。可以安全地忽略或重复的初始化应该放在tp_init处理程序中。一个好的经验法则是,对于不可变类型,所有初始化都应该在tp_new 中进行,而对于可变类型,大多数初始化应该推迟到tp_init。
这就是为什么您在中创建对象本身tp_new并在tp_init. 创建 C++ 对象是初始化的一部分。由于tp_init文档说明
这个函数对应类的__init__ ()方法。和__init__ ()一样,可以在不调用__init__ ()的情况下创建实例,也可以通过再次调用其__init__ ()方法来重新初始化一个实例。
您需要bridge->m_pycxx_object != nullptr在失败或引发错误时检查并删除已初始化的实例。
在tp_dealloc你然后销毁 Python 对象。由于 C++ 对象是这个对象的一部分,因此它也需要在那里销毁。
回到配对:您tp_alloc在内部tp_new和tp_free内部调用tp_dealloc。所以 { tp_alloc, tp_free} 和 { tp_new, tp_dealloc} 应该被视为对。
| 归档时间: |
|
| 查看次数: |
1048 次 |
| 最近记录: |