diff options
Diffstat (limited to 'plugins/pychrysalide/helpers.c')
-rw-r--r-- | plugins/pychrysalide/helpers.c | 292 |
1 files changed, 206 insertions, 86 deletions
diff --git a/plugins/pychrysalide/helpers.c b/plugins/pychrysalide/helpers.c index d361c3e..0c84278 100644 --- a/plugins/pychrysalide/helpers.c +++ b/plugins/pychrysalide/helpers.c @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * helpers.c - 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. * @@ -39,7 +39,6 @@ #include <i18n.h> #include <common/extstr.h> -#include <plugins/dt.h> #include "access.h" @@ -217,6 +216,53 @@ bool has_python_method(PyObject *module, const char *method) * * * Paramètres : target = propriétaire de la routine visée. * * method = désignation de la fonction à appeler. * +* * +* Description : Indique si une routine Python possède une implémentation. * +* * +* Retour : Bilan de l'analyse. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool has_python_implementation_method(PyObject *module, const char *method) +{ + bool result; /* Bilan à retourner */ + PyObject *func; /* Fonction visée */ + const PyMethodDef *def; /* Définition de la fonction */ + + result = (PyObject_HasAttrString(module, method) == 1); + + if (result) + { + func = PyObject_GetAttrString(module, method); + assert(func != NULL); + + result = PyCallable_Check(func); + + if (func->ob_type == &PyCFunction_Type) + { + def = ((PyCFunctionObject *)func)->m_ml; + + assert(strcmp(def->ml_name, method) == 0); + + result = (def->ml_meth != not_yet_implemented_method); + + } + + Py_DECREF(func); + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : target = propriétaire de la routine visée. * +* method = désignation de la fonction à appeler. * * args = arguments à associer à l'opération. * * * * Description : Appelle une routine Python. * @@ -517,75 +563,10 @@ bool register_python_module_object(PyObject *module, PyTypeObject *type) * * ******************************************************************************/ -PyObject *python_constructor_with_dynamic_gtype(PyTypeObject *type, GType gbase, PyObject *args, PyObject *kwds) -{ - PyObject *result; /* Objet à retourner */ - PyTypeObject *base; /* Type parent version Python */ - bool first_time; /* Evite les multiples passages*/ - GType gtype; /* Nouveau type de processeur */ - bool status; /* Bilan d'un enregistrement */ - - /* Validations diverses */ - - base = pygobject_lookup_class(gbase); - - if (type == base) - goto simple_way; - - /* Mise en place d'un type dédié */ - - first_time = (g_type_from_name(type->tp_name) == 0); - - gtype = build_dynamic_type(gbase, type->tp_name, NULL, NULL, NULL); - - if (first_time) - { - status = register_class_for_dynamic_pygobject(gtype, type); - - if (!status) - { - result = NULL; - goto exit; - } - - } - - /* On crée, et on laisse ensuite la main à PyGObject_Type.tp_init() */ - - simple_way: - - result = PyType_GenericNew(type, args, kwds); - - exit: - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : type = type du nouvel objet à mettre en place. * -* gbase = type de base natif. * -* cinit = procédure d'initialisation de la classe associée. * -* args = éventuelle liste d'arguments. * -* kwds = éventuel dictionnaire de valeurs mises à disposition.* -* * -* Description : Accompagne la création d'une instance dérivée en Python. * -* * -* Retour : Nouvel objet Python mis en place ou NULL en cas d'échec. * -* * -* Remarques : - * -* * -******************************************************************************/ - -PyObject *python_abstract_constructor_with_dynamic_gtype(PyTypeObject *type, GType gbase, GClassInitFunc cinit, PyObject *args, PyObject *kwds) +PyObject *python_abstract_constructor(PyTypeObject *type, GType gbase, PyObject *args, PyObject *kwds) { PyObject *result; /* Objet à retourner */ PyTypeObject *base; /* Type parent version Python */ - bool first_time; /* Evite les multiples passages*/ - GType gtype; /* Nouveau type de processeur */ - bool status; /* Bilan d'un enregistrement */ /* Validations diverses */ @@ -598,24 +579,6 @@ PyObject *python_abstract_constructor_with_dynamic_gtype(PyTypeObject *type, GTy goto exit; } - /* Mise en place d'un type dédié */ - - first_time = (g_type_from_name(type->tp_name) == 0); - - gtype = build_dynamic_type(gbase, type->tp_name, cinit, NULL, NULL); - - if (first_time) - { - status = register_class_for_dynamic_pygobject(gtype, type); - - if (!status) - { - result = NULL; - goto exit; - } - - } - /* On crée, et on laisse ensuite la main à PyGObject_Type.tp_init() */ result = PyType_GenericNew(type, args, kwds); @@ -1159,6 +1122,60 @@ int forward_pygobjet_init(PyObject *self) /****************************************************************************** * * +* Paramètres : type = type Python à ausculter. * +* * +* Description : Détermine si un type Python est implémenté en C ou non. * +* * +* Retour : Bilan de l'analyse. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool pytype_has_native_implementation(const PyTypeObject *type) +{ + bool result; /* Bilan à retourner */ + GType gtype; /* Type associé à la classe */ + + static GQuark pygobject_custom_key = 0; /* Clef d'accès direct */ + + /** + * Dans les sources de PyGObject, la fonction pyg_type_register() de + * gi/gimodule.c, appelée depuis gi/types.py, contient la bribe de code + * suivante : + * + * // Mark this GType as a custom python type + * g_type_set_qdata(instance_type, pygobject_custom_key, + * GINT_TO_POINTER (1)); + * + * La fonction pyi_object_register_types() de gi/pygobject-object.c indique + * la clef associée au Quark : + * + * pygobject_custom_key = g_quark_from_static_string("PyGObject::custom"); + * + * Enfin, une fonction inspirante est codée dans le fichier gi/pygi-type.c : + * + * gboolean pyg_gtype_is_custom(GType gtype) + * { + * return g_type_get_qdata (gtype, pygobject_custom_key) != NULL; + * } + * + */ + + if (pygobject_custom_key == 0) + pygobject_custom_key = g_quark_from_static_string("PyGObject::custom"); + + gtype = pyg_type_from_object((PyObject *)type); + + result = (g_type_get_qdata(gtype, pygobject_custom_key) == NULL); + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : arg = argument quelconque à tenter de convertir. * * dst = destination des valeurs récupérées en cas de succès. * * * @@ -1486,6 +1503,109 @@ int convert_to_gdk_rgba(PyObject *arg, void *dst) +/****************************************************************************** +* * +* Paramètres : arg = argument quelconque à tenter de convertir. * +* dst = destination des valeurs récupérées en cas de succès. * +* * +* Description : Tente de convertir en tableau de chaînes de caractères. * +* * +* Retour : Bilan de l'opération, voire indications supplémentaires. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int convert_to_sequence_to_charp_array(PyObject *arg, void *dst) +{ + int result; /* Bilan à retourner */ + charp_array_t *array; /* Tableau à constituer */ + size_t i; /* Boucle de parcours */ + PyObject *value; /* Valeur brute d'un élément */ + + array = (charp_array_t *)dst; + + /* Nettoyage ? */ + if (arg == NULL) + { + result = 1; + goto clean; + } + + else + { + result = 0; + + if (PySequence_Check(arg) != 1) + goto done; + + array->length = PySequence_Length(arg); + + array->values = calloc(array->length, sizeof(char *)); + + for (i = 0; i < array->length; i++) + { + value = PySequence_ITEM(arg, i); + + if (!PyUnicode_Check(value)) + { + Py_DECREF(value); + goto clean; + } + + array->values[i] = strdup(PyUnicode_DATA(value)); + + Py_DECREF(value); + + } + + result = Py_CLEANUP_SUPPORTED; + + } + + done: + + return result; + + clean: + + clean_charp_array(array); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : array = tableau de chaînes de caractères à traiter. * +* * +* Description : Libère de la mémoire un tableau de chaînes de caractères. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void clean_charp_array(charp_array_t *array) +{ + size_t i; /* Boucle de parcours */ + + for (i = 0; i < array->length; i++) + if (array->values[i] != NULL) + free(array->values[i]); + + if (array->values != NULL) + free(array->values); + + array->values = NULL; + array->length = 0; + +} + + + /* ---------------------------------------------------------------------------------- */ /* TRANSFERT DES VALEURS CONSTANTES */ /* ---------------------------------------------------------------------------------- */ |