Python C-API Object Distribution

I want to use new and delete operators to create and destroy my objects.

The problem is that python breaks it down into several stages. tp_new, tp_init and tp_alloc to create and tp_del, tp_free and tp_dealloc to destroy. However, C ++ only has a new one that selects and completely constructs the object and deletes that destroys and frees the object.

Which of the tp_ * python methods do I need to provide and what should they do?

I also want to be able to create an object directly in C ++, for example, "PyObject" obj = new MyExtensionObject (args); "Will I also need to somehow overload the new operator to support this?

I would also like to be able to subclass my extension types in python, is there anything special I need to do to support this?

I am using python 3.0.1.

EDIT: ok, tp_init seems to make the objects too oversized for what I am doing (e.g. take a Texture object, changing the contents after creation in order, but change its fundamental aspects like size, bitdept, etc. existing material C ++, which assumes that such things are fixed). If I don't implement it, it just stops people calling __init__ AFTER the creation (or at least ignoring the call, such as a tuple). Or should I have some flag that throws an exception or somthing if tp_init is called more than once on the same object?

, , , .

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();
    }
    ...
};
+5
2

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__ ​​ .

, "++ ", . tp_alloc ++, __new__ ( factory), __init__ . ++ Python.

http://www.python.org/download/releases/2.2/descrintro/, , __new__ __init__.

, " ++". , Python, , ++. Boost:: Python . .;)

+11

API- python, python , .

:.

 // 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)));
0

All Articles