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