首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >{tp_alloc,tp_dealloc}和{tp_new,tp_free}应视为对吗?

{tp_alloc,tp_dealloc}和{tp_new,tp_free}应视为对吗?
EN

Stack Overflow用户
提问于 2015-02-01 13:25:04
回答 1查看 1.4K关注 0票数 7

在tp_alloc中创建的任何东西都应该在tp_dealloc中销毁,这是真的吗?与{tp_new,tp_free}类似?

这看起来很明显是对称的,但我很感激你的澄清。

我的实际用例是:我有:

代码语言:javascript
复制
class OSClass : PyObject {...}

class Final : OSClass {...}

因此,相应的PyTypeObject pto有:

代码语言:javascript
复制
pto->tp_basicsize = sizeof(FinalClass)
pto->tp_dealloc = (destructor) 
                  [](PyObject* pyob) { PyMem_Free(pyob); };

但是,新样式类分别存储PyObject及其对应的C++对象,因此工作方式不同。

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

并在tp_dealloc中销毁它们

这是正确的/最佳的吗?

代码:

代码语言:javascript
复制
// 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);
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-02-01 21:12:01

从你的 documentation

tp_new函数应该调用subtype->tp_alloc(subtype, nitems)为对象分配空间,然后只进行绝对必要的进一步初始化。可以安全地忽略或重复的初始化应该放在tp_init处理程序中。一个很好的经验法则是,对于不可变类型,所有初始化都应该在tp_new中进行,而对于可变类型,大多数初始化应该推迟到tp_init

这就是为什么在tp_new中创建对象并在tp_init中初始化对象的原因。创建C++对象是初始化的一部分。因为 documentation状态

这个函数对应于类的__init__()方法。与__init__()一样,可以在不调用__init__()的情况下创建实例,也可以通过再次调用其__init__()方法重新初始化实例。

您需要检查bridge->m_pycxx_object != nullptr并在失败时删除已经初始化的实例,或者引发错误。

然后在tp_dealloc中销毁Python对象。因为C++对象是这个对象的一部分,所以也需要在那里销毁它。

回到配对:在tp_new中调用tp_free,在tp_dealloc中调用tp_free。因此,{tp_alloctp_free}和{tp_newtp_dealloc}应视为对。

票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28263177

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档