summaryrefslogtreecommitdiff
path: root/plugins/pychrysalide/helpers.h
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/pychrysalide/helpers.h')
-rw-r--r--plugins/pychrysalide/helpers.h108
1 files changed, 96 insertions, 12 deletions
diff --git a/plugins/pychrysalide/helpers.h b/plugins/pychrysalide/helpers.h
index cc82bba..745d013 100644
--- a/plugins/pychrysalide/helpers.h
+++ b/plugins/pychrysalide/helpers.h
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* helpers.h - prototypes pour la simplification des interactions de base avec Python
*
- * Copyright (C) 2018-2020 Cyrille Bagard
+ * Copyright (C) 2018-2024 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -34,6 +34,9 @@
#endif
+#include <i18n.h>
+
+
/* ---------------------- ACCELERATEURS POUR PYTHON UNIQUEMENT ---------------------- */
@@ -47,6 +50,9 @@ int convert_to_callable(PyObject *, void *);
/* Indique si une routine Python existe ou non. */
bool has_python_method(PyObject *, const char *);
+/* Indique si une routine Python possède une implémentation. */
+bool has_python_implementation_method(PyObject *, const char *);
+
/* Appelle une routine Python. */
PyObject *run_python_method(PyObject *, const char *, PyObject *);
@@ -126,7 +132,7 @@ bool register_python_module_object(PyObject *, PyTypeObject *);
PYTHON_GETSET_DEF("is_" #name, base ## _is_ ## name, NULL, ATTRIB_RO doc, NULL)
#define PYTHON_HAS_DEF_FULL(name, base, doc) \
- PYTHON_GETSET_DEF(#name, base ## _has_ ## name, NULL, ATTRIB_RO doc, NULL)
+ PYTHON_GETSET_DEF("has_" #name, base ## _has_ ## name, NULL, ATTRIB_RO doc, NULL)
#define PYTHON_RAWGET_DEF_FULL(name, base, doc) \
PYTHON_GETSET_DEF(#name, base ## _ ## name, NULL, ATTRIB_RO doc, NULL)
@@ -152,14 +158,11 @@ bool register_python_module_object(PyObject *, PyTypeObject *);
*
* Cf. http://stackoverflow.com/questions/20432335/can-python-abstract-base-classes-inherit-from-c-extensions
*/
-#define APPLY_ABSTRACT_FLAG(tp) tp->tp_new = PyBaseObject_Type.tp_new
+#define APPLY_ABSTRACT_FLAG(tp) tp->tp_new = PyBaseObject_Type.tp_new // REMME
/* Accompagne la création d'une instance dérivée en Python. */
-PyObject *python_constructor_with_dynamic_gtype(PyTypeObject *, GType, PyObject *, PyObject *);
-
-/* Accompagne la création d'une instance dérivée en Python. */
-PyObject *python_abstract_constructor_with_dynamic_gtype(PyTypeObject *, GType, GClassInitFunc, PyObject *, PyObject *);
+PyObject *python_abstract_constructor(PyTypeObject *, GType, PyObject *, PyObject *);
#define CREATE_DYN_CONSTRUCTOR(pyname, gbase) \
@@ -167,22 +170,41 @@ static PyObject *py_ ## pyname ## _new(PyTypeObject *, PyObject *, PyObject *);
static PyObject *py_ ## pyname ## _new(PyTypeObject *type, PyObject *args, PyObject *kwds) \
{ \
PyObject *result; /* Objet à retourner */ \
- result = python_constructor_with_dynamic_gtype(type, gbase, args, kwds); \
+ result = PyType_GenericNew(type, args, kwds); \
return result; \
}
-#define CREATE_DYN_ABSTRACT_CONSTRUCTOR(pyname, gbase, cinit) \
+#define CREATE_DYN_ABSTRACT_CONSTRUCTOR(pyname, gbase) \
static PyObject *py_ ## pyname ## _new(PyTypeObject *, PyObject *, PyObject *); \
static PyObject *py_ ## pyname ## _new(PyTypeObject *type, PyObject *args, PyObject *kwds) \
{ \
PyObject *result; /* Objet à retourner */ \
- result = python_abstract_constructor_with_dynamic_gtype(type, gbase, (GClassInitFunc)cinit, \
- args, kwds); \
+ result = python_abstract_constructor(type, gbase, args, kwds); \
return result; \
}
+/**
+ * Les initialisations de classes engagées par les appels à pyg_register_class_init()
+ * ne se déclenchent qu'après les initialisations complètes des classes côté GObject.
+ *
+ * Typiquement, pour une déclinaison Python du type PythonModule, sont appelées
+ * successivement les fonctions suivantes :
+ * - g_plugin_module_class_init() ;
+ * - g_python_plugin_class_init() ;
+ * - py_plugin_module_init_gclass().
+ *
+ * Il est alors impératif de considérer les pointeurs de fonction déjà en place
+ * afin de ne par remplacer les implémentations de GPythonPlugin par les
+ * wrappers par défaut de PythonModule.
+ */
+
+#define PY_CLASS_SET_WRAPPER(field, ptr) \
+ if (field == NULL) \
+ field = ptr;
+
+
/* Marque l'interdiction d'une instanciation depuis Python. */
PyObject *no_python_constructor_allowed(PyTypeObject *, PyObject *, PyObject *);
@@ -206,6 +228,41 @@ PyTypeObject *define_python_dynamic_type(const PyTypeObject *);
/**
+ * Prise en compte d'éventuelles exceptions levées dans les implémentations.
+ *
+ * Par exemple :
+ * - du code Python exécute une fonction implémentée en C ;
+ * - cette dernière fait appel à un Wrapper C qui sollicite du code
+ * d'implémentation Python.
+ *
+ * Cette seconde étape peut lever une exception (impletation manquante ou
+ * implémentation levant une exception.
+ *
+ * Les codes C des étapes 1 et 2 ne dispose pas de mécanismes pour transmettre
+ * le détail des éventuelles exceptions, mais Python le mémorise.
+ */
+
+#define UPDATE_RESULT_IF_RAISED_EXCEPTION(val) \
+ do \
+ { \
+ if (PyErr_Occurred() != NULL) \
+ result = val; \
+ } \
+ while (0)
+
+#define CLEAN_RESULT_IF_RAISED_EXCEPTION(val) \
+ do \
+ { \
+ if (PyErr_Occurred() != NULL) \
+ { \
+ Py_XDECREF(result); \
+ result = NULL; \
+ } \
+ } \
+ while (0)
+
+
+/**
* pygobject_new() prend en compte les références flottantes au moment de la
* construction d'un objet Python.
*
@@ -231,11 +288,23 @@ bool register_class_for_pygobject(PyObject *, GType, PyTypeObject *);
bool register_interface_for_pygobject(PyObject *, GType, PyTypeObject *, const GInterfaceInfo *);
/* Enregistre un type Python dérivant d'un type GLib dynamique. */
-bool register_class_for_dynamic_pygobject(GType, PyTypeObject *);
+bool register_class_for_dynamic_pygobject(GType, PyTypeObject *); // REMME
/* Fait suivre à la partie GObject une initialisation nouvelle. */
int forward_pygobjet_init(PyObject *);
+/* Détermine si un type Python est implémenté en C ou non. */
+bool pytype_has_native_implementation(const PyTypeObject *);
+
+#define check_for_native_parent(obj) \
+ ({ \
+ bool __result; \
+ __result = pytype_has_native_implementation((obj)->ob_type->tp_base); \
+ if (!__result) \
+ PyErr_SetString(PyExc_RuntimeError, _("object parent is not a native type")); \
+ __result; \
+ })
+
/* Tente de convertir en valeur GType. */
int convert_to_gtype(PyObject *, void *);
@@ -283,6 +352,21 @@ int convert_to_gdk_rgba(PyObject *, void *);
#endif
+/* Tableau de chaînes de caractères converti */
+typedef struct _charp_array_t
+{
+ char **values; /* Liste de chaînes textuelles */
+ size_t length; /* Taille de cette liste */
+
+} charp_array_t;
+
+/* Tente de convertir en tableau de chaînes de caractères. */
+int convert_to_sequence_to_charp_array(PyObject *, void *);
+
+/* Libère de la mémoire un tableau de chaînes de caractères. */
+void clean_charp_array(charp_array_t *);
+
+
/* ----------------------- TRANSFERT DES VALEURS CONSTANTES ------------------------- */