gpt4 book ai didi

c++ - Python C-API 对象分配

转载 作者:太空狗 更新时间:2023-10-29 21:33:10 27 4
gpt4 key购买 nike

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

问题是 python 似乎将其分为几个阶段。 tp_new、tp_init 和 tp_alloc 用于创建,tp_del、tp_free 和 tp_dealloc 用于销毁。然而,c++ 只有分配和完全构造对象的 new 和破坏和释放对象的 delete。

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

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

我还希望能够在 python 中子类化我的扩展类型,我需要做些什么来支持它吗?

我正在使用 python 3.0.1。

编辑:好的,tp_init 似乎使对象对于我正在做的事情来说有点过于可变(例如,获取一个 Texture 对象,在创建后更改内容很好,但是更改它的基本方面,例如大小,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, 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.htmlhttp://docs.python.org/3.0/extending/newtypes.html介绍如何制作您自己的类型。

tp_alloc 为实例进行低级内存分配。这相当于 malloc(),加上将 refcnt 初始化为 1。Python 有它自己的分配器 PyType_GenericAlloc,但是一个类型可以实现一个专门的分配器。

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

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

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

__new__ 和 __init__ 之间的区别称为 two-stage initialization , 或 two-phase initialization .

你说“c++ 有新的”但那是不正确的。 tp_alloc对应C++中的自定义arena分配器,__new__对应自定义类型分配器(工厂函数),__init__更像是构造函数。最后一个链接更多地讨论了 C++ 和 Python 风格之间的相似之处。

另请阅读 http://www.python.org/download/releases/2.2/descrintro/有关 __new__ 和 __init__ 如何交互的详细信息。

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

关于c++ - Python C-API 对象分配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/573275/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com