summaryrefslogtreecommitdiff
path: root/plugins/pychrysa/helpers.c
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2017-08-12 15:08:53 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2017-08-12 15:08:53 (GMT)
commitfcc78751e1e733b8662fde7d5e8ac6023cb34582 (patch)
treed57096d898446b6c2387bd2bd7ead0d3f175b617 /plugins/pychrysa/helpers.c
parenta9328553fc558bca2e75f2c93b35acc5518d9568 (diff)
Fixed many mistakes in the Python bindings.
Diffstat (limited to 'plugins/pychrysa/helpers.c')
-rw-r--r--plugins/pychrysa/helpers.c152
1 files changed, 151 insertions, 1 deletions
diff --git a/plugins/pychrysa/helpers.c b/plugins/pychrysa/helpers.c
index a0a828f..17a396d 100644
--- a/plugins/pychrysa/helpers.c
+++ b/plugins/pychrysa/helpers.c
@@ -27,9 +27,15 @@
#include <assert.h>
#include <pygobject.h>
#include <stdarg.h>
+#include <string.h>
+/* ---------------------------------------------------------------------------------- */
+/* ACCELERATEURS POUR PYTHON UNIQUEMENT */
+/* ---------------------------------------------------------------------------------- */
+
+
/******************************************************************************
* *
* Paramètres : status = bilan de comparaison à traduire. *
@@ -242,6 +248,126 @@ bool PyDict_AddStringConstant(PyTypeObject *obj_type, const char *key, const cha
}
+
+/* ---------------------------------------------------------------------------------- */
+/* CONFORTS CIBLANT PYGOBJECT */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : spec = définition à mettre en place dynamiquement. *
+* *
+* Description : Définit dans le tas de Python un nouveau type. *
+* *
+* Retour : Nouveau type prêt à emploi. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyTypeObject *define_python_dynamic_type(const PyTypeObject *spec)
+{
+ 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éé */
+
+ /**
+ * 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.
+ */
+
+ hobj = (PyHeapTypeObject *)result;
+
+ s = strrchr(spec->tp_name, '.');
+
+ if (s == NULL)
+ s = (char *)spec->tp_name;
+ else
+ s++;
+
+ hobj->ht_name = PyUnicode_FromString(s);
+ assert(hobj->ht_name != NULL);
+
+ hobj->ht_qualname = hobj->ht_name;
+ Py_INCREF(hobj->ht_qualname);
+
+ 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;
+
+ hobj->ht_cached_keys = _PyDict_NewKeysForClass();
+
+
+
+
+#if 0
+ if (type->tp_itemsize == 0)
+ (void)PyObject_INIT(result, type);
+ else
+ (void) PyObject_INIT_VAR((PyVarObject *)result, type, 0);
+
+ if (PyType_IS_GC(type))
+ _PyObject_GC_TRACK(result);
+#endif
+
+ return result;
+
+}
+
+
/******************************************************************************
* *
* Paramètres : module = module où conserver une référence au type créé. *
@@ -259,6 +385,7 @@ bool PyDict_AddStringConstant(PyTypeObject *obj_type, const char *key, const cha
bool _register_class_for_pygobject(PyObject *dict, GType gtype, PyTypeObject *type, PyTypeObject *base, ...)
{
+ bool result; /* Bilan à retourner */
Py_ssize_t size; /* Taille de liste actuelle */
PyObject *static_bases; /* Base(s) de l'objet */
va_list ap; /* Parcours des arguments */
@@ -314,10 +441,33 @@ bool _register_class_for_pygobject(PyObject *dict, GType gtype, PyTypeObject *ty
va_end(ap);
+
+
+ /*
+#0 0x000055555565aad4 in insertdict (mp=0x7fffe7c2c8a8, key='GenConfig', hash=262970853803706525, value=<unknown at remote 0x7ffff6bd9ce0>) at ../Objects/dictobject.c:801
+#1 0x000055555565bf62 in PyDict_SetItem (op={'__doc__': 'Python module for Chrysalide.glibext', '__name__': 'pychrysalide.glibext', 'BufferLine': <type at remote 0x7ffff6bd9760>, '__spec__': None, 'ConfigParam': <type at remote 0x7ffff6bd9a00>, '__package__': None, 'Buffercache': <type at remote 0x7ffff6bd95c0>, 'ConfigParamIterator': <type at remote 0x7ffff6bd9fc0>, '__loader__': None}, key='GenConfig', value=<unknown at remote 0x7ffff6bd9ce0>) at ../Objects/dictobject.c:1227
+#2 0x00005555556610b0 in PyDict_SetItemString (v={'__doc__': 'Python module for Chrysalide.glibext', '__name__': 'pychrysalide.glibext', 'BufferLine': <type at remote 0x7ffff6bd9760>, '__spec__': None, 'ConfigParam': <type at remote 0x7ffff6bd9a00>, '__package__': None, 'Buffercache': <type at remote 0x7ffff6bd95c0>, 'ConfigParamIterator': <type at remote 0x7ffff6bd9fc0>, '__loader__': None}, key=0x7ffff69cd0bd "GenConfig", item=<unknown at remote 0x7ffff6bd9ce0>) at ../Objects/dictobject.c:2870
+#3 0x00007ffff69b3d12 in _register_class_for_pygobject (dict={'__doc__': 'Python module for Chrysalide.glibext', '__name__': 'pychrysalide.glibext', 'BufferLine': <type at remote 0x7ffff6bd9760>, '__spec__': None, 'ConfigParam': <type at remote 0x7ffff6bd9a00>, '__package__': None, 'Buffercache': <type at remote 0x7ffff6bd95c0>, 'ConfigParamIterator': <type at remote 0x7ffff6bd9fc0>, '__loader__': None}, gtype=93824998785328, type=0x7ffff6bd9ce0 <py_generic_config_type>, base=0x7fffe80e72a0 <PyGObject_Type>) at helpers.c:320
+ */
+
+
+
+ //type->tp_weaklistoffset = offsetof(PyGObject, weakreflist);
+ //type->tp_dictoffset = offsetof(PyGObject, inst_dict);
+
pygobject_register_class(dict, NULL, gtype, type, static_bases);
+ if (PyErr_Occurred() == NULL)
+ result = true;
+
+ else
+ {
+ PyErr_Print();
+ result = false;
+ }
+
assert(PyErr_Occurred() == NULL);
- return true;
+ return result;
}