From 89f802045b71299ba70a8df17ca09d5fcc37cf99 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Fri, 27 May 2022 18:31:43 +0200 Subject: Avoid calls to Python _PyDict_NewKeysForClass() internal function. --- plugins/pychrysalide/helpers.c | 129 ++++++++++++++--------------------------- 1 file changed, 45 insertions(+), 84 deletions(-) diff --git a/plugins/pychrysalide/helpers.c b/plugins/pychrysalide/helpers.c index b04c801..8e7c10c 100644 --- a/plugins/pychrysalide/helpers.c +++ b/plugins/pychrysalide/helpers.c @@ -717,7 +717,7 @@ PyObject *not_yet_implemented_getter(PyObject *self, void *closure) /****************************************************************************** * * -* Paramètres : spec = définition à mettre en place dynamiquement. * +* Paramètres : otype = définition à mettre en place dynamiquement. * * * * Description : Définit dans le tas de Python un nouveau type. * * * @@ -727,102 +727,63 @@ PyObject *not_yet_implemented_getter(PyObject *self, void *closure) * * ******************************************************************************/ -PyTypeObject *define_python_dynamic_type(const PyTypeObject *spec) +PyTypeObject *define_python_dynamic_type(const PyTypeObject *otype) { PyTypeObject *result; /* Définition créée à renvoyer */ - PyTypeObject *type; /* Type de tous les types */ - size_t size; /* Taille de la définition */ - char *s; /* Marqueur de début de chaîne */ - PyHeapTypeObject *hobj; /* Version réelle du type créé */ + PyType_Slot slots[10]; /* Emplacements pour infos */ + PyType_Spec spec; /* Définition du type */ + PyType_Slot *iter; /* Boucle de parcours */ + PyObject *bases; /* Bases de construction */ - /** - * Le cahier des charges est ici d'éviter les erreurs suivantes : - * - * TypeError: type 'XXX' is not dynamically allocated but its base type 'YYY' is dynamically allocated - * Fatal Python error: unexpected exception during garbage collection - * - * L'allocation dynamique est marquée par le fanion Py_TPFLAGS_HEAPTYPE. - * - * Une des rares fonctions qui appliquent ce fanion est PyType_FromSpecWithBases(), - * mais elle appelle ensuite PyType_Ready(), ce qui est incompatible avec des modifications - * utltérieures avant un appel à pygobject_register_class(). - * - * Le code suivant s'inspire fortement des méthodes originales de Python, - * dont les mécanismes employés par PyType_GenericAlloc(). - */ - - type = &PyType_Type; - size = _PyObject_SIZE(type); - - if (PyType_IS_GC(type)) - result = (PyTypeObject *)_PyObject_GC_Malloc(size); - else - result = (PyTypeObject *)PyObject_MALLOC(size); - - if (type->tp_flags & Py_TPFLAGS_HEAPTYPE) - Py_INCREF(type); - - /* Définitions sommaires */ - - memset(result, 0, sizeof(PyHeapTypeObject)); - - memcpy(result, spec, sizeof(PyTypeObject)); - - result->tp_flags |= Py_TPFLAGS_HEAPTYPE; - - /* Définitions des noms */ - - /** - * Pour un type dynamique, les désignations ne s'appuient pas sur la partie réservée - * au type, mais sur les données suivantes (cf. type_name() et type_qualname()). - * - * Les deux fonctions désignées sont par ailleurs facilement accessibles : - * - * #0 0x0000555555689bf0 in type_qualname (...) at Objects/typeobject.c:393 - * #1 0x000055555568b3b4 in type_repr (...) at Objects/typeobject.c:855 - * #2 0x0000555555693574 in object_str (...) at Objects/typeobject.c:3511 - * #3 0x0000555555670d02 in PyObject_Str (...) at Objects/object.c:535 - * ... - * - * On s'inspire donc du contenu de PyType_FromSpecWithBases() pour éviter tout - * plantage du fait de données non initialisées. - */ + bases = PyTuple_Pack(1, &PyType_Type); - hobj = (PyHeapTypeObject *)result; + spec.name = otype->tp_name; + spec.basicsize = otype->tp_basicsize; + spec.flags = otype->tp_flags; + spec.slots = slots; - s = strrchr(spec->tp_name, '.'); - - if (s == NULL) - s = (char *)spec->tp_name; - else - s++; + iter = &slots[0]; - hobj->ht_name = PyUnicode_FromString(s); - assert(hobj->ht_name != NULL); - - hobj->ht_qualname = hobj->ht_name; - Py_INCREF(hobj->ht_qualname); + if (otype->tp_doc != NULL) + { + iter->slot = Py_tp_doc; + iter->pfunc = (void *)otype->tp_doc; + iter++; + } - result->tp_as_async = &hobj->as_async; - result->tp_as_number = &hobj->as_number; - result->tp_as_sequence = &hobj->as_sequence; - result->tp_as_mapping = &hobj->as_mapping; - result->tp_as_buffer = &hobj->as_buffer; + if (otype->tp_methods != NULL) + { + iter->slot = Py_tp_methods; + iter->pfunc = otype->tp_methods; + iter++; + } - hobj->ht_cached_keys = _PyDict_NewKeysForClass(); + if (otype->tp_getset != NULL) + { + iter->slot = Py_tp_getset; + iter->pfunc = otype->tp_getset; + iter++; + } + if (otype->tp_init != NULL) + { + iter->slot = Py_tp_init; + iter->pfunc = otype->tp_init; + iter++; + } + if (otype->tp_new != NULL) + { + iter->slot = Py_tp_new; + iter->pfunc = otype->tp_new; + iter++; + } + iter->slot = 0; -#if 0 - if (type->tp_itemsize == 0) - (void)PyObject_INIT(result, type); - else - (void) PyObject_INIT_VAR((PyVarObject *)result, type, 0); + result = (PyTypeObject *)PyType_FromSpecWithBases(&spec, bases); - if (PyType_IS_GC(type)) - _PyObject_GC_TRACK(result); -#endif + Py_DECREF(bases); return result; -- cgit v0.11.2-87-g4458