diff options
Diffstat (limited to 'plugins/pychrysalide')
-rw-r--r-- | plugins/pychrysalide/analysis/loaded.c | 791 | ||||
-rw-r--r-- | plugins/pychrysalide/analysis/storage/serialize.c | 2 | ||||
-rw-r--r-- | plugins/pychrysalide/gtkext/dockable.c | 32 | ||||
-rw-r--r-- | plugins/pychrysalide/gtkext/graph/cluster.c | 6 | ||||
-rw-r--r-- | plugins/pychrysalide/helpers.c | 56 | ||||
-rw-r--r-- | plugins/pychrysalide/helpers.h | 3 |
6 files changed, 824 insertions, 66 deletions
diff --git a/plugins/pychrysalide/analysis/loaded.c b/plugins/pychrysalide/analysis/loaded.c index 768b11c..e3b2625 100644 --- a/plugins/pychrysalide/analysis/loaded.c +++ b/plugins/pychrysalide/analysis/loaded.c @@ -33,22 +33,52 @@ #include <i18n.h> -#include <analysis/loaded.h> +#include <analysis/loaded-int.h> #include <core/global.h> +#include "content.h" #include "../access.h" #include "../helpers.h" -#define LOADED_CONTENT_DOC \ - "The LoadedContent interface is an intermediary level of abstraction" \ - " for all loaded binary contents to analyze." \ - "\n" \ - "No matter if the loaded content comes from an ELF file or XML data," \ - " some basic features are available here." +/* ------------------------ GLUE POUR CREATION DEPUIS PYTHON ------------------------ */ + + +/* Procède à l'initialisation de l'interface de génération. */ +static void py_loaded_content_interface_init(GLoadedContentIface *, gpointer *); + +/* Fournit le contenu représenté de l'élément chargé. */ +static GBinContent *py_loaded_content_get_content_wrapper(const GLoadedContent *); + +/* Fournit le format associé à l'élément chargé. */ +static char *py_loaded_content_get_format_name_wrapper(const GLoadedContent *); + +/* Lance l'analyse propre à l'élément chargé. */ +static bool py_loaded_content_analyze_wrapper(GLoadedContent *, bool, bool, wgroup_id_t, GtkStatusStack *); +/* Fournit le désignation associée à l'élément chargé. */ +static char *py_loaded_content_describe_wrapper(const GLoadedContent *, bool); + +/* Détermine le nombre de vues disponibles pour un contenu. */ +static unsigned int py_loaded_content_count_views_wrapper(const GLoadedContent *); + +/* Fournit le nom d'une vue donnée d'un contenu chargé. */ +static char *py_loaded_content_get_view_name_wrapper(const GLoadedContent *, unsigned int); + +/* Met en place la vue initiale pour un contenu chargé. */ +static GtkWidget *py_loaded_content_build_default_view_wrapper(GLoadedContent *); + +/* Met en place la vue demandée pour un contenu chargé. */ +static GtkWidget *py_loaded_content_build_view_wrapper(GLoadedContent *, unsigned int); + +/* Retrouve l'indice correspondant à la vue donnée d'un contenu. */ +static unsigned int py_loaded_content_get_view_index_wrapper(GLoadedContent *, GtkWidget *); + + + +/* ------------------------- CONNEXION AVEC L'API DE PYTHON ------------------------- */ /* Lance l'analyse propre à l'élément chargé. */ @@ -83,6 +113,690 @@ static PyObject *py_loaded_content_get_format_name(PyObject *, void *); +/* ---------------------------------------------------------------------------------- */ +/* GLUE POUR CREATION DEPUIS PYTHON */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : iface = interface GLib à initialiser. * +* unused = adresse non utilisée ici. * +* * +* Description : Procède à l'initialisation de l'interface de génération. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void py_loaded_content_interface_init(GLoadedContentIface *iface, gpointer *unused) +{ +#define LOADED_CONTENT_DOC \ + "The LoadedContent interface is an intermediary level of abstraction" \ + " for all loaded binary contents to analyze." \ + "\n" \ + "No matter if the loaded content comes from an ELF file or XML data," \ + " some basic features are available here." \ + "\n" \ + "A typical class declaration for a new implementation looks like:\n" \ + "\n" \ + " class NewImplem(GObject.Object, LoadedContent):\n" \ + " ...\n" \ + "\n" \ + "The following methods have to be defined for new implementations:\n" \ + "* pychrysalide.analysis.storage.LoadedContent._get_content();\n" \ + "* pychrysalide.analysis.storage.LoadedContent._get_format_name();\n" \ + "* pychrysalide.analysis.storage.LoadedContent._analyze();\n" \ + "* pychrysalide.analysis.storage.LoadedContent._describe();\n" \ + "* pychrysalide.analysis.storage.LoadedContent._count_views();\n" \ + "* pychrysalide.analysis.storage.LoadedContent._get_view_name();\n" \ + "* pychrysalide.analysis.storage.LoadedContent._build_default_view();\n"\ + "* pychrysalide.analysis.storage.LoadedContent._build_view();\n" \ + "* pychrysalide.analysis.storage.LoadedContent._get_view_index();\n" + + iface->get_content = py_loaded_content_get_content_wrapper; + iface->get_format_name = py_loaded_content_get_format_name_wrapper; + + iface->analyze = py_loaded_content_analyze_wrapper; + + iface->describe = py_loaded_content_describe_wrapper; + + iface->count_views = py_loaded_content_count_views_wrapper; + iface->get_view_name = py_loaded_content_get_view_name_wrapper; + iface->build_def_view = py_loaded_content_build_default_view_wrapper; + iface->build_view = py_loaded_content_build_view_wrapper; + iface->get_view_index = py_loaded_content_get_view_index_wrapper; + +} + + +/****************************************************************************** +* * +* Paramètres : content = élément chargé à manipuler. * +* * +* Description : Fournit le contenu représenté de l'élément chargé. * +* * +* Retour : Contenu représenté. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GBinContent *py_loaded_content_get_content_wrapper(const GLoadedContent *content) +{ + GBinContent *result; /* Contenu interne à renvoyer */ + PyGILState_STATE gstate; /* Sauvegarde d'environnement */ + PyObject *pyobj; /* Objet Python concerné */ + PyObject *pyret; /* Bilan de consultation */ + +#define LOADED_CONTENT_GET_CONTENT_WRAPPER PYTHON_WRAPPER_DEF \ +( \ + _get_content, "$self", \ + METH_VARARGS, \ + "Abstract method used to get the binary content linked to the" \ + " loaded content. The result is provided as a" \ + " pychrysalide.analysis.BinContent instance." \ +) + + result = NULL; + + gstate = PyGILState_Ensure(); + + pyobj = pygobject_new(G_OBJECT(content)); + + if (has_python_method(pyobj, "_get_content")) + { + pyret = run_python_method(pyobj, "_get_content", NULL); + + if (pyret != NULL) + { + if (convert_to_binary_content(pyret, &result) != 1) + PyErr_Clear(); + + Py_DECREF(pyret); + + } + + } + + Py_DECREF(pyobj); + + PyGILState_Release(gstate); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : content = élément chargé à manipuler. * +* * +* Description : Fournit le format associé à l'élément chargé. * +* * +* Retour : Format associé à l'élément chargé. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static char *py_loaded_content_get_format_name_wrapper(const GLoadedContent *content) +{ + char *result; /* Contenu interne à renvoyer */ + PyGILState_STATE gstate; /* Sauvegarde d'environnement */ + PyObject *pyobj; /* Objet Python concerné */ + PyObject *pyret; /* Bilan de consultation */ + int ret; /* Validité d'une conversion */ + +#define LOADED_CONTENT_GET_FORMAT_NAME_WRAPPER PYTHON_WRAPPER_DEF \ +( \ + _get_format_name, "$self", \ + METH_VARARGS, \ + "Abstract method used to provide the aw name of the format connected" \ + " to the loaded content.\n" \ + "\n" \ + "The name associated to a loaded Elf binary is for instance 'elf'." \ +) + + result = NULL; + + gstate = PyGILState_Ensure(); + + pyobj = pygobject_new(G_OBJECT(content)); + + if (has_python_method(pyobj, "_get_format_name")) + { + pyret = run_python_method(pyobj, "_get_format_name", NULL); + + if (pyret != NULL) + { + ret = PyUnicode_Check(pyret); + + if (ret) + result = strdup(PyUnicode_AsUTF8(pyret)); + + Py_DECREF(pyret); + + } + + } + + Py_DECREF(pyobj); + + PyGILState_Release(gstate); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : content = élément chargé à manipuler. * +* connect = organise le lancement des connexions aux serveurs. * +* cache = précise si la préparation d'un rendu est demandée. * +* gid = groupe de travail dédié. * +* status = barre de statut à tenir informée. * +* * +* Description : Lance l'analyse propre à l'élément chargé. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool py_loaded_content_analyze_wrapper(GLoadedContent *content, bool connect, bool cache, wgroup_id_t gid, GtkStatusStack *status) +{ + bool result; /* Bilan à retourner */ + PyGILState_STATE gstate; /* Sauvegarde d'environnement */ + PyObject *connect_obj; /* Ordre de connexion */ + PyObject *cache_obj; /* Usage du cache */ + PyObject *args; /* Arguments pour l'appel */ + PyObject *pyobj; /* Objet Python concerné */ + PyObject *pyret; /* Bilan de consultation */ + +#define LOADED_CONTENT_ANALYZE_WRAPPER PYTHON_WRAPPER_DEF \ +( \ + _analyze, "$self, connect, cache, gid, status", \ + METH_VARARGS, \ + "Abstract method used to start the analysis of the loaded binary." \ + "\n" \ + "The *connect* parameter defines if connections to database servers" \ + " (internal and/or remote) will be established. The default value" \ + " depends on the running mode: if the analysis is run from the GUI," \ + " the binary will get connected to servers; in batch mode, no" \ + " connection will be made." \ + "\n" \ + "The *cache* parameter rules the build of the cache for rendering" \ + " lines. The same behavior relative to the running mode applies." \ + "\n" \ + "The identifier refers to the working queue used to process the" \ + " analysis. A reference to the main status bar may also be provided," \ + " as a pychrysalide.gtkext.StatusStack instance if running in" \ + " graphical mode or None otherwise." \ +) + + result = false; + + gstate = PyGILState_Ensure(); + + pyobj = pygobject_new(G_OBJECT(content)); + + if (has_python_method(pyobj, "_analyze")) + { + connect_obj = connect ? Py_True : Py_False; + Py_INCREF(connect_obj); + + cache_obj = cache ? Py_True : Py_False; + Py_INCREF(cache_obj); + + args = PyTuple_New(4); + PyTuple_SetItem(args, 0, connect_obj); + PyTuple_SetItem(args, 1, cache_obj); + PyTuple_SetItem(args, 2, PyLong_FromUnsignedLong(gid)); + PyTuple_SetItem(args, 3, pygobject_new(G_OBJECT(status))); + + pyret = run_python_method(pyobj, "_analyze", args); + + if (pyret != NULL) + { + result = (pyret == Py_True); + Py_DECREF(pyret); + } + + Py_DECREF(args); + + } + + Py_DECREF(pyobj); + + PyGILState_Release(gstate); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : content = élément chargé à consulter. * +* full = précise s'il s'agit d'une version longue ou non. * +* * +* Description : Fournit le désignation associée à l'élément chargé. * +* * +* Retour : Description courante. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static char *py_loaded_content_describe_wrapper(const GLoadedContent *content, bool full) +{ + char *result; /* Description à retourner */ + PyGILState_STATE gstate; /* Sauvegarde d'environnement */ + PyObject *full_obj; /* Précision sur la longueur */ + PyObject *args; /* Arguments pour l'appel */ + PyObject *pyobj; /* Objet Python concerné */ + PyObject *pyret; /* Bilan de consultation */ + int ret; /* Validité d'une conversion */ + +#define LOADED_CONTENT_DESCRIBE_WRAPPER PYTHON_WRAPPER_DEF \ +( \ + _describe, "$self, full", \ + METH_VARARGS, \ + "Abstract method used to describe the loaded content.\n" \ + "\n" \ + "The boolean *full* parameter shapes the size of the returned string.\n" \ + "\n" \ + "This method is mainly used to provide a label (or a tooltip text)" \ + " for tabs in the graphical main window." \ +) + + result = NULL; + + gstate = PyGILState_Ensure(); + + pyobj = pygobject_new(G_OBJECT(content)); + + if (has_python_method(pyobj, "_describe")) + { + full_obj = full ? Py_True : Py_False; + Py_INCREF(full_obj); + + args = PyTuple_New(1); + PyTuple_SetItem(args, 0, full_obj); + + pyret = run_python_method(pyobj, "_describe", args); + + if (pyret != NULL) + { + ret = PyUnicode_Check(pyret); + + if (ret) + result = strdup(PyUnicode_AsUTF8(pyret)); + + Py_DECREF(pyret); + + } + + Py_DECREF(args); + + } + + Py_DECREF(pyobj); + + PyGILState_Release(gstate); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : content = contenu chargé à consulter. * +* * +* Description : Détermine le nombre de vues disponibles pour un contenu. * +* * +* Retour : Quantité strictement positive. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static unsigned int py_loaded_content_count_views_wrapper(const GLoadedContent *content) +{ + unsigned int result; /* Quantité de vues à renvoyer */ + PyGILState_STATE gstate; /* Sauvegarde d'environnement */ + PyObject *pyobj; /* Objet Python concerné */ + PyObject *pyret; /* Bilan de consultation */ + int ret; /* Validité d'une conversion */ + +#define LOADED_CONTENT_COUNT_VIEWS_WRAPPER PYTHON_WRAPPER_DEF \ +( \ + _count_views, "$self", \ + METH_VARARGS, \ + "Abstract method used to compute the quantity of available" \ + " views for the loaded binary." \ +) + + result = 0; + + gstate = PyGILState_Ensure(); + + pyobj = pygobject_new(G_OBJECT(content)); + + if (has_python_method(pyobj, "_count_views")) + { + pyret = run_python_method(pyobj, "_count_views", NULL); + + if (pyret != NULL) + { + ret = PyLong_Check(pyret); + + if (ret) + result = PyLong_AsUnsignedLong(pyret); + + Py_DECREF(pyret); + + } + + } + + Py_DECREF(pyobj); + + PyGILState_Release(gstate); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : content = contenu chargé à consulter. * +* index = indice de la vue ciblée. * +* * +* Description : Fournit le nom d'une vue donnée d'un contenu chargé. * +* * +* Retour : Désignation humainement lisible. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static char *py_loaded_content_get_view_name_wrapper(const GLoadedContent *content, unsigned int index) +{ + char *result; /* Désignation à retourner */ + PyGILState_STATE gstate; /* Sauvegarde d'environnement */ + PyObject *args; /* Arguments pour l'appel */ + PyObject *pyobj; /* Objet Python concerné */ + PyObject *pyret; /* Bilan de consultation */ + int ret; /* Validité d'une conversion */ + +#define LOADED_CONTENT_GET_VIEW_NAME_WRAPPER PYTHON_WRAPPER_DEF \ +( \ + _get_view_name, "$self, index", \ + METH_VARARGS, \ + "Abstract method used to provide the human readable name for" \ + " a given view of a loaded binary.\n" \ + "\n" \ + "Such a method is used in the graphical main window for" \ + " building menu labels." \ +) + + result = NULL; + + gstate = PyGILState_Ensure(); + + pyobj = pygobject_new(G_OBJECT(content)); + + if (has_python_method(pyobj, "_get_view_name")) + { + args = PyTuple_New(1); + PyTuple_SetItem(args, 0, PyLong_FromUnsignedLong(index)); + + pyret = run_python_method(pyobj, "_get_view_name", args); + + if (pyret != NULL) + { + ret = PyUnicode_Check(pyret); + + if (ret) + result = strdup(PyUnicode_AsUTF8(pyret)); + + Py_DECREF(pyret); + + } + + Py_DECREF(args); + + } + + Py_DECREF(pyobj); + + PyGILState_Release(gstate); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : content = contenu chargé à consulter. * +* * +* Description : Met en place la vue initiale pour un contenu chargé. * +* * +* Retour : Composant graphique nouveau. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GtkWidget *py_loaded_content_build_default_view_wrapper(GLoadedContent *content) +{ + GtkWidget *result; /* Support à retourner */ + PyGILState_STATE gstate; /* Sauvegarde d'environnement */ + PyObject *pyobj; /* Objet Python concerné */ + PyObject *pyret; /* Bilan de consultation */ + int ret; /* Validité d'une conversion */ + +#define LOADED_CONTENT_BUILD_DEFAULT_VIEW_WRAPPER PYTHON_WRAPPER_DEF \ +( \ + _build_default_view, "$self", \ + METH_VARARGS, \ + "Abstract method used to build a new widget for the default graphical" \ + " view of the loaded content." \ + "\n" \ + "This method is aimed to only be called from the GUI internals." \ + " It provides the first view displayed in the main Chrysalide window" \ + " after a binary loading." \ +) + + result = NULL; + + gstate = PyGILState_Ensure(); + + pyobj = pygobject_new(G_OBJECT(content)); + + if (has_python_method(pyobj, "_build_default_view")) + { + pyret = run_python_method(pyobj, "_build_default_view", NULL); + + if (pyret != NULL) + { + ret = convert_to_gtk_widget(pyret, &result); + + if (ret == 1) + g_object_ref(G_OBJECT(result)); + + Py_DECREF(pyret); + + } + + } + + Py_DECREF(pyobj); + + PyGILState_Release(gstate); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : content = contenu chargé à consulter. * +* index = indice de la vue ciblée. * +* * +* Description : Met en place la vue demandée pour un contenu chargé. * +* * +* Retour : Composant graphique nouveau. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GtkWidget *py_loaded_content_build_view_wrapper(GLoadedContent *content, unsigned int index) +{ + GtkWidget *result; /* Support à retourner */ + PyGILState_STATE gstate; /* Sauvegarde d'environnement */ + PyObject *args; /* Arguments pour l'appel */ + PyObject *pyobj; /* Objet Python concerné */ + PyObject *pyret; /* Bilan de consultation */ + int ret; /* Validité d'une conversion */ + +#define LOADED_CONTENT_BUILD_VIEW_WRAPPER PYTHON_WRAPPER_DEF \ +( \ + _build_view, "$self, index", \ + METH_VARARGS, \ + "Abstract method used to build a new widget for a given graphical view" \ + " of the loaded content.\n" \ + "\n" \ + "This method is aimed to only be called from the GUI internals." \ + " It provides a view displayed in the main Chrysalide window" \ + " once the binary is loaded." \ +) + + result = NULL; + + gstate = PyGILState_Ensure(); + + pyobj = pygobject_new(G_OBJECT(content)); + + if (has_python_method(pyobj, "_build_view")) + { + args = PyTuple_New(1); + PyTuple_SetItem(args, 0, PyLong_FromUnsignedLong(index)); + + pyret = run_python_method(pyobj, "_build_view", args); + + if (pyret != NULL) + { + ret = convert_to_gtk_widget(pyret, &result); + + if (ret == 1) + g_object_ref(G_OBJECT(result)); + + Py_DECREF(pyret); + + } + + Py_DECREF(args); + + } + + Py_DECREF(pyobj); + + PyGILState_Release(gstate); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : content = contenu chargé à consulter. * +* index = composant graphique en place. * +* * +* Description : Retrouve l'indice correspondant à la vue donnée d'un contenu.* +* * +* Retour : Indice de la vue représentée, ou -1 en cas d'erreur. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static unsigned int py_loaded_content_get_view_index_wrapper(GLoadedContent *content, GtkWidget *view) +{ + unsigned int result; /* Indice à retourner */ + PyGILState_STATE gstate; /* Sauvegarde d'environnement */ + PyObject *args; /* Arguments pour l'appel */ + PyObject *pyobj; /* Objet Python concerné */ + PyObject *pyret; /* Bilan de consultation */ + int ret; /* Validité d'une conversion */ + +#define LOADED_CONTENT_GET_VIEW_INDEX_WRAPPER PYTHON_WRAPPER_DEF \ +( \ + _get_view_index, "$self, view", \ + METH_VARARGS, \ + "Abstract method used to define the index of a given view for the" \ + " loaded binary.\n" \ + "\n" \ + "The view is provided as a GTK *widget*.\n" \ + "\n" \ + "The result is the index of the type of view, or -1 in case of error." \ +) + + result = 0; + + gstate = PyGILState_Ensure(); + + pyobj = pygobject_new(G_OBJECT(content)); + + if (has_python_method(pyobj, "_get_view_index")) + { + args = PyTuple_New(1); + PyTuple_SetItem(args, 0, pygobject_new(G_OBJECT(view))); + + pyret = run_python_method(pyobj, "_get_view_index", args); + + if (pyret != NULL) + { + ret = PyLong_Check(pyret); + + if (ret) + result = PyLong_AsUnsignedLong(pyret); + + Py_DECREF(pyret); + + } + + Py_DECREF(args); + + } + + Py_DECREF(pyobj); + + PyGILState_Release(gstate); + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* CONNEXION AVEC L'API DE PYTHON */ +/* ---------------------------------------------------------------------------------- */ + + /****************************************************************************** * * * Paramètres : self = contenu binaire à manipuler. * @@ -416,15 +1130,16 @@ static PyObject *py_loaded_content_build_default_view(PyObject *self, PyObject * GLoadedContent *content; /* Version GLib de l'élément */ GtkWidget *view; /* Composant GTK à transposer */ -#define LOADED_CONTENT_BUILD_DEFAULT_VIEW_METHOD PYTHON_METHOD_DEF \ -( \ - build_default_view, "$self", \ - METH_NOARGS, py_loaded_content, \ - "Build a new widget for the default graphical view of the loaded content." \ - "\n" \ - "This method is aimed to only be called from the GUI internals." \ - " It provides the first view displayed in the main Chrysalide window" \ - " after a binary loading." \ +#define LOADED_CONTENT_BUILD_DEFAULT_VIEW_METHOD PYTHON_METHOD_DEF \ +( \ + build_default_view, "$self", \ + METH_NOARGS, py_loaded_content, \ + "Build a new widget for the default graphical view of the loaded" \ + " content.\n" \ + "\n" \ + "This method is aimed to only be called from the GUI internals." \ + " It provides the first view displayed in the main Chrysalide window" \ + " after a binary loading." \ ) content = G_LOADED_CONTENT(pygobject_get(self)); @@ -461,15 +1176,16 @@ static PyObject *py_loaded_content_build_view(PyObject *self, PyObject *args) GLoadedContent *content; /* Version GLib de l'élément */ GtkWidget *view; /* Composant GTK à transposer */ -#define LOADED_CONTENT_BUILD_VIEW_METHOD PYTHON_METHOD_DEF \ -( \ - build_view, "$self, index", \ - METH_VARARGS, py_loaded_content, \ - "Build a new widget for a given graphical view of the loaded content." \ - "\n" \ - "This method is aimed to only be called from the GUI internals." \ - " It provides a view displayed in the main Chrysalide window" \ - " once the binary is loaded." \ +#define LOADED_CONTENT_BUILD_VIEW_METHOD PYTHON_METHOD_DEF \ +( \ + build_view, "$self, index", \ + METH_VARARGS, py_loaded_content, \ + "Build a new widget for a given graphical view of the loaded" \ + " content.\n" \ + "\n" \ + "This method is aimed to only be called from the GUI internals." \ + " It provides a view displayed in the main Chrysalide window" \ + " once the binary is loaded." \ ) ret = PyArg_ParseTuple(args, "I", &index); @@ -541,12 +1257,6 @@ static PyObject *py_loaded_content_get_view_index(PyObject *self, PyObject *args if (!ret) return NULL; - if (!GTK_IS_WIDGET(pygobject_get(widget_obj))) - { - PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to GTK widget"); - return NULL; - } - content = G_LOADED_CONTENT(pygobject_get(self)); widget = GTK_WIDGET(pygobject_get(widget_obj)); @@ -653,6 +1363,15 @@ static PyObject *py_loaded_content_get_format_name(PyObject *self, void *closure PyTypeObject *get_python_loaded_content_type(void) { static PyMethodDef py_loaded_content_methods[] = { + LOADED_CONTENT_GET_CONTENT_WRAPPER, + LOADED_CONTENT_GET_FORMAT_NAME_WRAPPER, + LOADED_CONTENT_ANALYZE_WRAPPER, + LOADED_CONTENT_DESCRIBE_WRAPPER, + LOADED_CONTENT_COUNT_VIEWS_WRAPPER, + LOADED_CONTENT_GET_VIEW_NAME_WRAPPER, + LOADED_CONTENT_BUILD_DEFAULT_VIEW_WRAPPER, + LOADED_CONTENT_BUILD_VIEW_WRAPPER, + LOADED_CONTENT_GET_VIEW_INDEX_WRAPPER, LOADED_CONTENT_ANALYZE_METHOD, LOADED_CONTENT_ANALYZE_AND_WAIT_METHOD, LOADED_CONTENT_DESCRIBE_METHOD, @@ -710,6 +1429,14 @@ bool ensure_python_loaded_content_is_registered(void) PyObject *module; /* Module à recompléter */ PyObject *dict; /* Dictionnaire du module */ + static GInterfaceInfo info = { /* Paramètres d'inscription */ + + .interface_init = (GInterfaceInitFunc)py_loaded_content_interface_init, + .interface_finalize = NULL, + .interface_data = NULL, + + }; + type = get_python_loaded_content_type(); if (!PyType_HasFeature(type, Py_TPFLAGS_READY)) @@ -718,7 +1445,7 @@ bool ensure_python_loaded_content_is_registered(void) dict = PyModule_GetDict(module); - if (!register_interface_for_pygobject(dict, G_TYPE_LOADED_CONTENT, type)) + if (!register_interface_for_pygobject_2(dict, G_TYPE_LOADED_CONTENT, type, &info)) return false; } diff --git a/plugins/pychrysalide/analysis/storage/serialize.c b/plugins/pychrysalide/analysis/storage/serialize.c index 67e1256..3e94271 100644 --- a/plugins/pychrysalide/analysis/storage/serialize.c +++ b/plugins/pychrysalide/analysis/storage/serialize.c @@ -97,7 +97,7 @@ static void py_serializable_object_interface_init(GSerializableObjectIface *ifac "\n" \ "The following methods have to be defined for new implementations:\n" \ "* pychrysalide.analysis.storage.SerializableObject._load();\n" \ - "* pychrysalide.analysis.storage.SerializableObject._store();\n" \ + "* pychrysalide.analysis.storage.SerializableObject._store();\n" iface->load = py_serializable_object_load_wrapper; iface->store = py_serializable_object_store_wrapper; diff --git a/plugins/pychrysalide/gtkext/dockable.c b/plugins/pychrysalide/gtkext/dockable.c index 8bb26b7..1412589 100644 --- a/plugins/pychrysalide/gtkext/dockable.c +++ b/plugins/pychrysalide/gtkext/dockable.c @@ -299,8 +299,6 @@ static GtkWidget *py_dockable_get_widget_wrapper(const GtkDockable *dockable) PyGILState_STATE gstate; /* Sauvegarde d'environnement */ PyObject *pyobj; /* Objet Python concerné */ PyObject *pyret; /* Bilan de consultation */ - PyObject *gtk_mod; /* Module Python Gtk */ - PyObject *widget_type; /* Module "GtkWidget" */ int ret; /* Bilan d'une conversion */ #define DOCKABLE_GET_WIDGET_WRAPPER PYTHON_WRAPPER_DEF \ @@ -312,6 +310,8 @@ static GtkWidget *py_dockable_get_widget_wrapper(const GtkDockable *dockable) "The result has to be a Gtk.Widget instance." \ ) + result = NULL; + gstate = PyGILState_Ensure(); pyobj = pygobject_new(G_OBJECT(dockable)); @@ -322,32 +322,10 @@ static GtkWidget *py_dockable_get_widget_wrapper(const GtkDockable *dockable) if (pyret != NULL) { - gtk_mod = PyImport_ImportModule("gi.repository.Gtk"); - - if (gtk_mod == NULL) - { - PyErr_SetString(PyExc_TypeError, "unable to find the Gtk Python module"); - goto done; - } - - widget_type = PyObject_GetAttrString(gtk_mod, "Widget"); - - Py_DECREF(gtk_mod); - - ret = PyObject_TypeCheck(pyret, (PyTypeObject *)widget_type); - - Py_DECREF(widget_type); - - if (!ret) - { - PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to GTK widget"); - goto done; - } - - result = GTK_WIDGET(pygobject_get(pyret)); - g_object_ref(G_OBJECT(result)); + ret = convert_to_gtk_widget(pyret, &result); - done: + if (ret == 1) + g_object_ref(G_OBJECT(result)); Py_DECREF(pyret); diff --git a/plugins/pychrysalide/gtkext/graph/cluster.c b/plugins/pychrysalide/gtkext/graph/cluster.c index c87655a..fc73276 100644 --- a/plugins/pychrysalide/gtkext/graph/cluster.c +++ b/plugins/pychrysalide/gtkext/graph/cluster.c @@ -161,12 +161,6 @@ static PyObject *py_graph_cluster_find_by_widget(PyObject *self, PyObject *args) if (!ret) return NULL; - if (!GTK_IS_WIDGET(pygobject_get(widget_obj))) - { - PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to GTK widget"); - return NULL; - } - cluster = G_GRAPH_CLUSTER(pygobject_get(self)); widget = GTK_WIDGET(pygobject_get(widget_obj)); diff --git a/plugins/pychrysalide/helpers.c b/plugins/pychrysalide/helpers.c index 5c7ae75..3cd528e 100644 --- a/plugins/pychrysalide/helpers.c +++ b/plugins/pychrysalide/helpers.c @@ -32,6 +32,7 @@ #include <stdlib.h> #include <string.h> #include <strings.h> +#include <gtk/gtk.h> #include <i18n.h> @@ -1132,6 +1133,61 @@ int convert_to_gobject(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 instance de composant GTK. * +* * +* Retour : Bilan de l'opération, voire indications supplémentaires. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int convert_to_gtk_widget(PyObject *arg, void *dst) +{ + int result; /* Bilan à retourner */ + PyObject *gtk_mod; /* Module Python Gtk */ + PyObject *widget_type; /* Module "GtkWidget" */ + int ret; /* Bilan d'une conversion */ + + result = 0; + + gtk_mod = PyImport_ImportModule("gi.repository.Gtk"); + + if (gtk_mod == NULL) + { + PyErr_SetString(PyExc_TypeError, "unable to find the Gtk Python module"); + goto done; + } + + widget_type = PyObject_GetAttrString(gtk_mod, "Widget"); + + Py_DECREF(gtk_mod); + + ret = PyObject_TypeCheck(arg, (PyTypeObject *)widget_type); + + Py_DECREF(widget_type); + + if (!ret) + { + PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to GTK widget"); + goto done; + } + + *((GtkWidget **)dst) = GTK_WIDGET(pygobject_get(arg)); + + result = 1; + + done: + + return result; + +} + + /* ---------------------------------------------------------------------------------- */ /* TRANSFERT DES VALEURS CONSTANTES */ diff --git a/plugins/pychrysalide/helpers.h b/plugins/pychrysalide/helpers.h index fd0ece7..a74a747 100644 --- a/plugins/pychrysalide/helpers.h +++ b/plugins/pychrysalide/helpers.h @@ -187,6 +187,9 @@ int forward_pygobjet_init(PyObject *); /* Tente de convertir en instance GObject. */ int convert_to_gobject(PyObject *, void *); +/* Tente de convertir en instance de composant GTK. */ +int convert_to_gtk_widget(PyObject *, void *); + /* ----------------------- TRANSFERT DES VALEURS CONSTANTES ------------------------- */ |