Python C-API 对象分配

在 Python 中,使用 C-API 进行对象分配时,需要考虑 tp_* 方法的使用方式。这些方法用于创建和销毁对象,包括 tp_new、tp_init 和 tp_alloc 用于创建,而 tp_del、tp_free 和 tp_dealloc 用于销毁。而在 C++ 中,可以使用 new 来分配和构造对象,同时使用 delete 来析构和释放对象。
在这里插入图片描述

2、解决方案

对于 Python 中的对象分配,需要提供相应的 tp_* 方法。

1)tp_alloc:

该方法用于分配对象的内存空间。它类似于 malloc(),但会将引用计数初始化为 1。Python 提供了自己的分配器 PyType_GenericAlloc,但类型也可以实现自己的专门分配器。

2)tp_new:

该方法与 Python 中的 new 方法相同。通常用于不可变对象,其中数据存储在实例本身,而不是数据指针。例如,字符串和元组将数据存储在实例中,而不是使用 char * 或 PyTuple *。在 tp_new 中,需要根据输入参数计算所需的内存量,然后调用 tp_alloc 获取内存,之后再初始化基本字段。该方法不需要调用 tp_alloc,也可以返回缓存对象。

3)tp_init:

该方法与 Python 中的 init 方法相同。大部分的初始化操作都应在此函数中进行。

4)其他方法:

除了上述方法外,还需要实现 tp_free 和 tp_dealloc 方法来释放对象占用的内存空间。

5)针对特定需求的解决方法:

对于希望直接在 C++ 中创建对象的情况,由于需要将 Python 异常转换为 C++ 异常,因此实现起来较为复杂。可以选择使用 Boost::Python 来简化这一过程。另外,也可以使用两阶段初始化来完成。

6)代码例子:

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();
    }
    ...
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值