微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

c – Python C-API对象分配

我想使用new和delete运算符来创建和销毁我的对象.

问题是python似乎将其分解为几个阶段.用于创建的tp_new,tp_init和tp_alloc以及用于销毁的tp_del,tp_free和tp_dealloc.但是c只有new,它分配并完全构造对象和删除对象的析构和解除分配.

我需要提供哪些python tp_ *方法以及它们必须做什么?

此外,我希望能够直接在c中创建对象,例如“PyObject * obj = new MyExtensionObject(args);”我是否还需要以某种方式重载新运算符以支持此操作?

我也希望能够在python中继承我的扩展类型,我需要做些什么来支持它?

我正在使用python 3.0.1.

编辑:
好吧,tp_init似乎让对象有点太可变了我正在做的事情(例如,使用一个Texture对象,在创建后改变内容很好,但改变它的基本方面,如size,bitdept等会打破很多现有的c假设那些东西是固定的).如果我不实现它,它只会阻止人们在构造之后调用__init__(或者至少忽略调用,就像元组一样).或者,如果在同一对象上多次调用tp_init,我是否应该有一些抛出异常或某事的标志?

除此之外,我认为其余的大部分已经排序.

extern "C"
{
    //creation + destruction
    PyObject* global_alloc(PyTypeObject *type,Py_ssize_t items)
    {
        return (PyObject*)new char[type->tp_basicsize + items*type->tp_itemsize];
    }
    void global_free(void *mem)
    {
        delete[] (char*)mem;
    }
}
template<class T> class ExtensionType
{
    PyTypeObject *t;
    ExtensionType()
    {
        t = new PyTypeObject();//not sure on this one,what is the "correct" way to create an empty type object
        memset((void*)t,sizeof(PyTypeObject));
        static PyVarObject init = {PyObject_HEAD_INIT,0};
        *((PyObject*)t) = init;

        t->tp_basicsize = sizeof(T);
        t->tp_itemsize  = 0;

        t->tp_name = "unkNown";

        t->tp_alloc   = (allocfunc) global_alloc;
        t->tp_free    = (freefunc)  global_free;
        t->tp_new     = (newfunc)   T::obj_new;
        t->tp_dealloc = (destructor)T::obj_dealloc;
        ...
    }
    ...bunch of methods for changing stuff...
    PyObject *Finalise()
    {
    ...
    }
};
template <class T> PyObjectExtension : public PyObject
{
...
    extern "C" static PyObject* obj_new(PyTypeObject *subtype,PyObject *args,PyObject *kwds)
    {
        void *mem = (void*)subtype->tp_alloc(subtype,0);
        return (PyObject*)new(mem) T(args,kwds)
    }
    extern "C" static void obj_dealloc(PyObject *obj)
    {
        ~T();
        obj->ob_type->tp_free(obj);//most of the time this is global_free(obj)
    }
...
};
class MyObject : PyObjectExtension<MyObject>
{
public:
    static PyObject* InitType()
    {
        ExtensionType<MyObject> extType();
        ...sets other stuff...
        return extType.Finalise();
    }
    ...
};

解决方法

这些文件文件是在 http://docs.python.org/3.0/c-api/typeobj.html
http://docs.python.org/3.0/extending/newtypes.html描述了如何制作自己的类型.

tp_alloc为实例执行低级别内存分配.这相当于malloc(),并将refcnt初始化为1.Python有自己的分配器PyType_GenericAlloc,但类型可以实现专门的分配器.

tp_new与Python的__new__相同.它通常用于不可变对象,其中数据存储在实例本身中,与指向数据的指针相比.例如,字符串和元组将它们的数据存储在实例中,而不是使用char *或PyTuple *.

对于这种情况,tp_new根据输入参数计算出需要多少内存,并调用tp_alloc来获取内存,然后初始化基本字段. tp_new不需要调用tp_alloc.例如,它可以返回一个缓存的对象.

tp_init与Python的__init__相同.您的大部分初始化应该在此函数中.

__new____init__间的区别称为two-stage initializationtwo-phase initialization.

你说“c只是有新的”但这不正确. tp_alloc对应于C中的自定义竞技场分配器,__ new__对应于自定义类型分配器(工厂函数),而__init__更像是构造函数.最后一个链接更多地讨论了C和Python风格之间的相似之处.

有关__new____init__如何交互的详细信息,请阅读http://www.python.org/download/releases/2.2/descrintro/.

你写的是你想“直接用c创建对象”.这是相当困难的,因为至少你必须将在对象实例化期间发生的任何Python异常转换为C异常.您可以尝试查看Boost :: Python以获得有关此任务的一些帮助.或者您可以使用两阶段初始化.

原文地址:https://www.jb51.cc/c/118661.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐