我想使用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; } } templateclass 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, 0, 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 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 { public: static PyObject* InitType() { ExtensionType extType(); ...sets other stuff... return extType.Finalise(); } ... };
Andrew Dalke.. 11
这些文档是在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__之间的区别称为两阶段初始化或两阶段初始化.
你说" c ++只是有新的 "但这不正确.tp_alloc对应于C++中的自定义竞技场分配器,__ new__对应于自定义类型分配器(工厂函数),__ init__更像是构造函数.最后一个链接更多地讨论了C++和Python风格之间的相似之处.
另请阅读http://www.python.org/download/releases/2.2/descrintro/,了解__new__和__init__如何互动的详细信息.
你写的是你想"直接用c ++创建对象".这是相当困难的,因为至少你必须将在对象实例化期间发生的任何Python异常转换为C++异常.您可以尝试查看Boost :: Python以获得有关此任务的一些帮助.或者您可以使用两阶段初始化.;)
这些文档是在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__之间的区别称为两阶段初始化或两阶段初始化.
你说" c ++只是有新的 "但这不正确.tp_alloc对应于C++中的自定义竞技场分配器,__ new__对应于自定义类型分配器(工厂函数),__ init__更像是构造函数.最后一个链接更多地讨论了C++和Python风格之间的相似之处.
另请阅读http://www.python.org/download/releases/2.2/descrintro/,了解__new__和__init__如何互动的详细信息.
你写的是你想"直接用c ++创建对象".这是相当困难的,因为至少你必须将在对象实例化期间发生的任何Python异常转换为C++异常.您可以尝试查看Boost :: Python以获得有关此任务的一些帮助.或者您可以使用两阶段初始化.;)