resueltos que programacion poo otra orientada objetos objeto metodo llamar herencia ejercicios definir como codigo clases clase c++ python c python-3.x python-c-api

c++ - que - Asignación de objetos C-API Python



programacion orientada a objetos (2)

Quiero utilizar los operadores nuevos y eliminar para crear y destruir mis objetos.

El problema es que Python parece dividirlo en varias etapas. tp_new, tp_init y tp_alloc para la creación y tp_del, tp_free y tp_dealloc para la destrucción. Sin embargo, c ++ solo tiene una nueva que asigna y construye completamente el objeto y elimina lo que destruye y desasigna el objeto.

¿Cuál de los métodos de python tp_ * debo proporcionar y qué deben hacer?

También quiero poder crear el objeto directamente en c ++, por ejemplo, "PyObject * obj = new MyExtensionObject (args);" ¿También necesitaré sobrecargar al nuevo operador de alguna manera para apoyar esto?

También me gustaría poder subclasificar mis tipos de extensión en Python, ¿hay algo especial que deba hacer para apoyar esto?

Estoy usando Python 3.0.1.

EDIT: ok, tp_init parece hacer que los objetos sean demasiado mutables para lo que estoy haciendo (por ejemplo, tomar un objeto Texture, cambiar los contenidos después de la creación está bien, pero cambiar aspectos fundamentales como tamaño, bitdept, etc. se romperá muchas cosas de c ++ existentes que asumen que ese tipo de cosas son fijas). Si no lo implemento, simplemente detendrá a las personas que llaman __init__ DESPUÉS de que se construya (o al menos ignore la llamada, como lo hace tuple). ¿O debería tener alguna bandera que arroje una excepción o algo si tp_init se invoca más de una vez en el mismo objeto?

Además de eso, creo que tengo la mayor parte del resto ordenado.

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


No conozco en absoluto las API de Python, pero si Python divide la asignación y la inicialización, debería poder utilizar la ubicación nueva.

p.ej:

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


La documentación para estos está en http://docs.python.org/3.0/c-api/typeobj.html y http://docs.python.org/3.0/extendiendo/newtypes.html describe cómo hacer su propio tipo .

tp_alloc hace la asignación de memoria de bajo nivel para la instancia. Esto es equivalente a malloc (), además de inicializar el refcnt a 1. Python tiene su propio asignador, PyType_GenericAlloc, pero un tipo puede implementar un asignador especializado.

tp_new es lo mismo que __new__ de Python. Por lo general, se utiliza para objetos inmutables donde los datos se almacenan en la instancia en sí, en comparación con un puntero a los datos. Por ejemplo, las cadenas y las tuplas almacenan sus datos en la instancia, en lugar de utilizar un char * o un PyTuple *.

Para este caso, tp_new averigua cuánta memoria se necesita, en función de los parámetros de entrada, y llama a tp_alloc para obtener la memoria, luego inicializa los campos esenciales. tp_new no necesita llamar a tp_alloc. Por ejemplo, puede devolver un objeto en caché.

tp_init es lo mismo que __init__ de Python. La mayor parte de su inicialización debe estar en esta función.

La distinción entre __new__ y __init__ se denomina inicialización de dos etapas o inicialización de dos fases .

Usted dice " c ++ solo tiene novedades ", pero eso no es correcto. tp_alloc corresponde a un asignador de arena personalizado en C ++, __new__ corresponde a un asignador de tipo personalizado (una función de fábrica), y __init__ es más parecido al constructor. Ese último enlace analiza más sobre los paralelismos entre C ++ y el estilo de Python.

Lea también http://www.python.org/download/releases/2.2/descrintro/ para obtener detalles sobre cómo __new__ y __init__ interactúan.

Usted escribe que quiere "crear el objeto directamente en c ++". Eso es bastante difícil porque, como mínimo, tendrá que convertir cualquier excepción de Python que haya ocurrido durante la instanciación de objetos en una excepción de C ++. Puede intentar consultar Boost :: Python para obtener ayuda con esta tarea. O puede usar una inicialización de dos fases. ;)