Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/350.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ Python C-API对象分配_C++_Python_C_Python 3.x_Python C Api - Fatal编程技术网

C++ Python C-API对象分配

C++ Python C-API对象分配,c++,python,c,python-3.x,python-c-api,C++,Python,C,Python 3.x,Python C Api,我想使用new和delete操作符来创建和销毁我的对象 问题在于python似乎将其分为几个阶段。tp_new、tp_init和tp_alloc用于创建,tp_del、tp_free和tp_dealloc用于销毁。但是C++有新的分配和完全构造对象,并删除破坏和释放对象的删除。 我需要提供哪些python tp_*方法,它们必须做什么 也希望能够直接在C++ EG中创建对象:“PyObjultObj=新MyExtExeExpObjor(ARGS)”,“我是否还需要以某种方式重载新操作符来支持这个

我想使用new和delete操作符来创建和销毁我的对象

问题在于python似乎将其分为几个阶段。tp_new、tp_init和tp_alloc用于创建,tp_del、tp_free和tp_dealloc用于销毁。但是C++有新的分配和完全构造对象,并删除破坏和释放对象的删除。 我需要提供哪些python tp_*方法,它们必须做什么

也希望能够直接在C++ EG中创建对象:“PyObjultObj=新MyExtExeExpObjor(ARGS)”,“我是否还需要以某种方式重载新操作符来支持这个?” 我还希望能够在python中对我的扩展类型进行子类化,我需要做些什么来支持这一点吗

我正在使用python 3.0.1

编辑: 好的,TpjIn似乎使对象对我正在做的事情有点太可变(例如,在创建时,改变纹理对象,改变内容是很好的,但是改变它的基本方面,比如大小、BITDeT等)会破坏很多现有C++的东西,假设这些东西是固定的)。如果我不实现它,它只会停止人们在其构造之后调用_uinit _uu(或者至少像tuple那样忽略调用)。或者,如果在同一对象上多次调用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();
    }
    ...
};
extern“C”
{
//创造+毁灭
PyObject*全局分配(PyTypeObject*类型,Py配置项)
{
返回(PyObject*)新字符[type->tp_basicsize+items*type->tp_itemsize];
}
无效全局\u自由(无效*内存)
{
删除[](字符*)成员;
}
}
模板类扩展类型
{
PyTypeObject*t;
ExtensionType()
{
t=new PyTypeObject();//不确定在这个问题上,创建空类型对象的“正确”方法是什么
memset((void*)t,0,sizeof(PyTypeObject));
静态PyVarObject init={PyObject\u HEAD\u init,0};
*((PyObject*)t)=init;
t->tp_basicsize=sizeof(t);
t->tp_itemsize=0;
t->tp_name=“未知”;
t->tp_alloc=(allocfunc)全局_alloc;
t->tp_free=(freefunc)全局_free;
t->tp_new=(newfunc)t::obj_new;
t->tp_dealloc=(析构函数)t::obj_dealloc;
...
}
…一系列改变东西的方法。。。
PyObject*finalize()
{
...
}
};
模板PyObjectExtension:公共PyObject
{
...
外部“C”静态PyObject*对象新建(PyTypeObject*子类型,PyObject*参数,PyObject*kwds)
{
void*mem=(void*)子类型->tp_alloc(子类型,0);
return(PyObject*)new(mem)T(args,kwds)
}
外部“C”静态无效对象
{
~T();
obj->ob_type->tp_free(obj);//大多数情况下这是全局_free(obj)
}
...
};
类MyObject:PyObjectExtension
{
公众:
静态PyObject*InitType()
{
ExtensionType extType();
…设置其他内容。。。
返回extType.finalize();
}
...
};

我根本不知道python API,但是如果python将分配和初始化分开,您应该能够使用新的布局

e、 g:

//tp\u alloc
void*buffer=新字符[sizeof(MyExtensionObject)];
//tp_init或tp_new(不确定有什么区别)
新建(缓冲区)MyExtensionObject(args);
返回静态_cast(缓冲区);
...
//特普德尔酒店
myExtensionObject->~myExtensionObject();//呼叫数据传输员
//tp_dealoc(或tp_free?我也不知道python API)
删除[](static_cast(static_cast(myExtensionObject)));

这些文档位于和 描述如何创建自己的类型

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

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

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

tp_init与Python的uu init_uuu相同。大多数初始化都应该在这个函数中

_uuunew_uuuu和uuu init_uuuu之间的区别称为,或

你说“c++只是有新的”,但那是不对的。TPL OLLC对应于C++中的自定义竞技场分配器;最后一个链接讨论了C++和Python风格之间的相似性。 还可以阅读有关“新建”和“初始化”如何交互的详细信息


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

放置
new
将是直观的,但遗憾的是
new(p)Class(args)在调用构造函数之前执行零初始化,清除python分配/初始化代码放入对象内存的值(例如引用计数)。另外,使用
newchar[n]
则覆盖结构是危险的,因为保证的内存对齐仅为1。
 // tp_alloc
 void *buffer = new char[sizeof(MyExtensionObject)];
 // tp_init or tp_new (not sure what the distinction is there)
 new (buffer) MyExtensionObject(args);
 return static_cast<MyExtensionObject*>(buffer);

 ...
 // tp_del
 myExtensionObject->~MyExtensionObject(); // call dtor
 // tp_dealloc (or tp_free? again I don't know the python apis)
 delete [] (static_cast<char*>(static_cast<void*>(myExtensionObject)));