diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2024-12-08 17:16:57 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2024-12-08 17:17:15 (GMT) |
commit | 29a47836eb9dd9c21c81da904b7ad5372a538144 (patch) | |
tree | 34c0e39fade89fda69c769797f7540793eae1780 /plugins/pychrysalide/core.c | |
parent | f2ac79dbf64c8604095737ef4e809a25ad63eacb (diff) |
Improve support for the Python GObject Introspection (GI).
Diffstat (limited to 'plugins/pychrysalide/core.c')
-rw-r--r-- | plugins/pychrysalide/core.c | 96 |
1 files changed, 90 insertions, 6 deletions
diff --git a/plugins/pychrysalide/core.c b/plugins/pychrysalide/core.c index 8d69933..f63fd9e 100644 --- a/plugins/pychrysalide/core.c +++ b/plugins/pychrysalide/core.c @@ -394,12 +394,18 @@ static bool install_metaclass_for_python_gobjects(void) * * from _gi import types * - * On simule ici une déclaration similaire si nécessaire + * On simule ici une déclaration similaire si nécessaire, selon la valeur + * portée par PyGObject_Type.ob_base.ob_base.ob_type.tp_name : + * - "type" (PyType_Type) : état initial ; + * - "_GObjectMetaBase" : état revu. */ - result = false; + /** + * PyGObject_Type.ob_base.ob_base.ob_type != &PyType_Type ? + */ + result = (PyType_CheckExact(&PyGObject_Type) == 0); - if (PyType_CheckExact(&PyGObject_Type)) + if (!result) { gi_types_mod = PyImport_ImportModule("gi.types"); @@ -412,6 +418,11 @@ static bool install_metaclass_for_python_gobjects(void) } +#ifndef NDEBUG + if (result) + assert(strcmp(PyGObject_Type.ob_base.ob_base.ob_type->tp_name, "_GObjectMetaBase") == 0); +#endif + return result; } @@ -533,6 +544,8 @@ static void PyExit_pychrysalide(void) PyMODINIT_FUNC PyInit_pychrysalide(void) { PyObject *result; /* Module Python à retourner */ + PyTypeObject *py_gobj_def; /* Définition GObject courante */ + GQuark pygobject_class_key; /* Copie d'un accès GI interne */ bool status; /* Bilan des inclusions */ int ret; /* Bilan de préparatifs */ #ifdef PYTHON_PACKAGE @@ -583,7 +596,13 @@ PyMODINIT_FUNC PyInit_pychrysalide(void) } if (!is_current_abi_suitable()) + { + /** + * Un message d'erreur est défini par is_current_abi_suitable() en cas + * d'interpréteur pas adapté. + */ goto exit; + } if (pygobject_init(-1, -1, -1) == NULL) { @@ -592,7 +611,10 @@ PyMODINIT_FUNC PyInit_pychrysalide(void) } if (!install_metaclass_for_python_gobjects()) + { + PyErr_SetString(PyExc_SystemError, "unable to install metaclass for Python GObjects."); goto exit; + } /** * Le chargement forcé de l'espace GLib pour Python permet d'éviter un écueil, @@ -615,8 +637,10 @@ PyMODINIT_FUNC PyInit_pychrysalide(void) * from gi.repository import GLib * */ +#if 0 if (!import_namespace_from_gi_repository("GLib", "2.0")) goto exit; +#endif #if 0 #ifdef INCLUDE_GTK_SUPPORT @@ -637,6 +661,56 @@ PyMODINIT_FUNC PyInit_pychrysalide(void) register_access_to_python_module(py_chrysalide_module.m_name, result); + /** + * Les appels suivants procèdent à l'enregistrement de différents éléments + * dans l'espace de noms Python pour Chrysalide. + * + * Une majeure partie de ces éléments est constituée d'objets dérivés de + * GObject. Ce type d'objet (G_TYPE_OBJECT) est représenté par deux types + * en Python : + * + * - gi._gi.GObject, mis en place lors de l'importation du module gi. + * + * Ce dernier lance automatiquement l'importation du module natif gi._gi, + * lequel, via son initialisation dans la fonction PyInit__gi() + * (cf. ./gi/gimodule.c) lance un appel à pyi_object_register_types() + * qui procède à l'enregistrement du type "GObject" porté par la structure + * PyGObject_Type en correspondance au type GLib G_TYPE_OBJECT (cf. appel + * à pygobject_register_class() dans gi/pygobject-object.c). + * + * - gi.repository.GObject.Object, qui vient surclasser le type précédent + * lors d'un appel d'initialisation : from gi.repository import GObject. + * + * Cette seconde définition est destinée à apporter une représentation + * de l'introspection GObject de plus haut niveau pour l'utilisateur par + * rapport à celle de bas niveau gi._gi. + * + * Il demeure que la seconde définition est entièrement implémentée en Python + * et porte ainsi le fanion Py_TPFLAGS_HEAPTYPE, imposant cette même dernière + * propriétée à tous les objets qui en dérivent. + * + * Les définitions de Chrysalide sont cependant toutes statiques et donc + * incompatibles avec une définition gi.repository.GObject.Object, comme le + * pointent les validations opérées par PyType_Ready(). + * + * Une solution consiste ici à restaurer au besoin la définition gi._gi.GObject + * brute, effectuer les enregistrements de Chrysalide sur cette base, et + * remettre en place la définition éventuellement remplacée ensuite. + */ + + py_gobj_def = pygobject_lookup_class(G_TYPE_OBJECT); + + if (py_gobj_def != &PyGObject_Type) + { + Py_INCREF((PyObject *)py_gobj_def); + + /* Définition récupérée de pyi_object_register_types() */ + pygobject_class_key = g_quark_from_static_string("PyGObject::class"); + + g_type_set_qdata(G_TYPE_OBJECT, pygobject_class_key, &PyGObject_Type); + + } + status = true; if (status) status = add_features_module(result); @@ -689,7 +763,7 @@ PyMODINIT_FUNC PyInit_pychrysalide(void) PyErr_SetString(PyExc_SystemError, "failed to load all PyChrysalide components."); Py_DECREF(result); result = NULL; - goto exit; + goto exit_and_restore; } if (_standalone) @@ -701,7 +775,7 @@ PyMODINIT_FUNC PyInit_pychrysalide(void) PyErr_SetString(PyExc_SystemError, "failed to register a cleanup function."); Py_DECREF(result); result = NULL; - goto exit; + goto exit_and_restore; } /** @@ -733,7 +807,7 @@ PyMODINIT_FUNC PyInit_pychrysalide(void) LOG_ERROR_DL_N("dladdr"); Py_DECREF(result); result = NULL; - goto exit; + goto exit_and_restore; } self = g_plugin_module_new(info.dli_fname); @@ -769,6 +843,16 @@ PyMODINIT_FUNC PyInit_pychrysalide(void) } + exit_and_restore: + + if (py_gobj_def != &PyGObject_Type) + { + g_type_set_qdata(G_TYPE_OBJECT, pygobject_class_key, py_gobj_def); + + Py_DECREF((PyObject *)py_gobj_def); + + } + exit: if (result == NULL && !_standalone) |