summaryrefslogtreecommitdiff
path: root/plugins/pychrysalide/core.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/pychrysalide/core.c')
-rw-r--r--plugins/pychrysalide/core.c96
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)