diff options
Diffstat (limited to 'plugins/pychrysalide/helpers.h')
-rw-r--r-- | plugins/pychrysalide/helpers.h | 108 |
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 ------------------------- */ |