我想使用new和delete操作符来创建和销毁我的对象。
问题是python似乎把它分成了几个阶段。tp_new、tp_init和tp_alloc用于创建,tp_del、tp_free和tp_dealloc用于销毁。然而,c++只是有了新的分配和完全构造对象的方法,而删除则是销毁和释放对象的方法。
我需要提供哪些python tpú方法,它们必须做什么?
另外,我希望能够在c++中直接创建对象,例如“PyObject*obj=new MyExtensionObject(args);”我是否还需要以某种方式重载这个新操作符来支持它?
我也希望能够在python中对我的扩展类型进行子类化,需要做什么特殊的事情来支持它吗?
我正在使用Python3.0.1。
编辑: 好吧,tp_init似乎使对象对于我所做的工作来说有点太不稳定(例如,获取一个纹理对象,在创建后更改内容是很好的,但是更改它的基本方面,例如,大小、bitdept等,会破坏很多现有的c++东西,假设这些东西是固定的)。如果我不实现它,它只会在构造之后停止人们调用init(或者至少像tuple那样忽略这个调用)。或者如果在同一个对象上多次调用tp_init,是否应该有抛出异常或somthing的标志?
除此之外,我想我把剩下的大部分都整理好了。
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, 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 <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's_uunew相同。与指向数据的指针相比,它通常用于不可变对象,其中数据存储在实例本身中。例如,字符串和元组将其数据存储在实例中,而不是使用char*或PyTuple*。
对于这种情况,tp_new根据输入参数计算出需要多少内存,并调用tp_alloc获取内存,然后初始化基本字段。tp_new不需要调用tp_alloc。例如,它可以返回缓存的对象。
tp_init与Python的初始化相同。大多数初始化都应该在这个函数中。
new和init之间的区别叫做two-stage initialization,或者two-phase initialization。
你说“c++刚刚有了新的”,但这不正确。TPL OLLC对应于C++中的自定义竞技场分配器;最后一个链接更多地讨论C++和Python风格之间的相似之处。
还可以阅读http://www.python.org/download/releases/2.2/descrintro/了解有关new和init如何交互的详细信息。
你写的是你想“在c++中直接创建对象”。这是相当困难的,因为至少你必须将在对象实例化期间发生的任何Python异常转换成C++异常。您可以尝试查看Boost::Python以获得有关此任务的帮助。或者可以使用两阶段初始化。;)
我根本不知道pythonapi,但是如果python将分配和初始化分开,您应该能够使用placement new。
例如:
相关问题 更多 >
编程相关推荐