summaryrefslogtreecommitdiff
path: root/plugins/pychrysalide/plugins/plugin.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/pychrysalide/plugins/plugin.c')
-rw-r--r--plugins/pychrysalide/plugins/plugin.c606
1 files changed, 246 insertions, 360 deletions
diff --git a/plugins/pychrysalide/plugins/plugin.c b/plugins/pychrysalide/plugins/plugin.c
index bd9cdfe..b013345 100644
--- a/plugins/pychrysalide/plugins/plugin.c
+++ b/plugins/pychrysalide/plugins/plugin.c
@@ -51,21 +51,31 @@
/* ------------------------ GLUE POUR CREATION DEPUIS PYTHON ------------------------ */
-/* Accompagne la création d'une instance dérivée en Python. */
-static PyObject *py_plugin_module_new(PyTypeObject *, PyObject *, PyObject *);
-
/* Initialise la classe des greffons d'extension. */
static void py_plugin_module_init_gclass(GPluginModuleClass *, gpointer);
+CREATE_DYN_ABSTRACT_CONSTRUCTOR(plugin_module, G_TYPE_PLUGIN_MODULE, py_plugin_module_init_gclass);
+
/* Initialise une instance sur la base du dérivé de GObject. */
static int py_plugin_module_init(PyObject *self, PyObject *args, PyObject *kwds);
/* Encadre une étape de la vie d'un greffon. */
static bool py_plugin_module_manage_wrapper(GPluginModule *);
+/* Assiste la désactivation d'un greffon. */
+static bool py_plugin_module_exit(GPluginModule *);
+
/* Accompagne la fin du chargement des modules natifs. */
static void py_plugin_module_notify_plugins_loaded_wrapper(GPluginModule *, PluginAction);
+/* Fournit le nom brut associé au greffon par défaut. */
+static PyObject *py_plugin_module_get_modname_by_default(PyObject *, PyObject *);
+
+/* Fournit le nom brut associé au greffon. */
+static char *py_plugin_module_get_modname_wrapper(const GPluginModule *);
+
+#ifdef INCLUDE_GTK_SUPPORT
+
/* Complète une liste de resources pour thème. */
static void py_plugin_module_include_theme_wrapper(const GPluginModule *, PluginAction, gboolean, char ***, size_t *);
@@ -75,6 +85,8 @@ static void py_plugin_module_notify_panel_creation_wrapper(const GPluginModule *
/* Rend compte d'un affichage ou d'un retrait de panneau. */
static void py_plugin_module_notify_panel_docking_wrapper(const GPluginModule *, PluginAction, GPanelItem *, bool);
+#endif
+
/* Procède à une opération liée à un contenu binaire. */
static void py_plugin_module_handle_binary_content_wrapper(const GPluginModule *, PluginAction, GBinContent *, wgroup_id_t, GtkStatusStack *);
@@ -98,42 +110,6 @@ static void py_plugin_module_detect_external_tools_wrapper(const GPluginModule *
-/* --------------------- INTERFACE INTERNE POUR GREFFONS PYTHON --------------------- */
-
-
-/* Ligne de représentation de code binaire (instance) */
-struct _GPythonPlugin
-{
- GPluginModule parent; /* Instance parente */
-
-};
-
-
-/* Ligne de représentation de code binaire (classe) */
-struct _GPythonPluginClass
-{
- GPluginModuleClass parent; /* Classe parente */
-
-};
-
-
-/* Initialise la classe des greffons Python. */
-static void g_python_plugin_class_init(GPythonPluginClass *);
-
-/* Initialise l'instance d'un greffon Python. */
-static void g_python_plugin_init(GPythonPlugin *);
-
-/* Supprime toutes les références externes. */
-static void g_python_plugin_dispose(GPythonPlugin *);
-
-/* Description : Procède à la libération totale de la mémoire. */
-static void g_python_plugin_finalize(GPythonPlugin *);
-
-/* Fournit le nom brut associé au greffon. */
-static char *g_python_plugin_get_modname(const GPythonPlugin *);
-
-
-
/* ------------------------- MODULE PYTHON POUR LES SCRIPTS ------------------------- */
@@ -161,69 +137,6 @@ static PyObject *py_plugin_module_get_interface(PyObject *, void *);
/******************************************************************************
* *
-* Paramètres : type = type du nouvel objet à mettre en place. *
-* 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 : - *
-* *
-******************************************************************************/
-
-static PyObject *py_plugin_module_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
- PyObject *result; /* Objet à retourner */
- PyTypeObject *base; /* Type de base à dériver */
- bool first_time; /* Evite les multiples passages*/
- GType gtype; /* Nouveau type de processeur */
- bool status; /* Bilan d'un enregistrement */
-
- /* Validations diverses */
-
- base = get_python_plugin_module_type();
-
- if (type == base)
- {
- result = NULL;
- PyErr_Format(PyExc_RuntimeError, _("%s is an abstract class"), type->tp_name);
- goto exit;
- }
-
- /* Mise en place d'un type dédié */
-
- first_time = (g_type_from_name(type->tp_name) == 0);
-
- gtype = build_dynamic_type(G_TYPE_PYTHON_PLUGIN, type->tp_name,
- (GClassInitFunc)py_plugin_module_init_gclass, NULL, NULL);
-
- if (first_time)
- {
- status = register_class_for_dynamic_pygobject(gtype, type, base);
-
- 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);
-
- exit:
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
* Paramètres : class = classe à initialiser. *
* unused = données non utilisées ici. *
* *
@@ -239,13 +152,17 @@ static void py_plugin_module_init_gclass(GPluginModuleClass *class, gpointer unu
{
class->init = NULL;
class->manage = py_plugin_module_manage_wrapper;
- class->exit = NULL;
+ class->exit = py_plugin_module_exit;
class->plugins_loaded = py_plugin_module_notify_plugins_loaded_wrapper;
+ class->get_modname = py_plugin_module_get_modname_wrapper;
+
+#ifdef INCLUDE_GTK_SUPPORT
class->include_theme = py_plugin_module_include_theme_wrapper;
class->notify_panel = py_plugin_module_notify_panel_creation_wrapper;
class->notify_docking = py_plugin_module_notify_panel_docking_wrapper;
+#endif
class->handle_content = py_plugin_module_handle_binary_content_wrapper;
class->handle_loaded = py_plugin_module_handle_loaded_content_wrapper;
@@ -498,6 +415,51 @@ static bool py_plugin_module_manage_wrapper(GPluginModule *plugin)
/******************************************************************************
* *
* Paramètres : plugin = greffon à manipuler. *
+* *
+* Description : Assiste la désactivation d'un greffon. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool py_plugin_module_exit(GPluginModule *plugin)
+{
+ bool result; /* Bilan à faire remonter */
+ plugin_interface *final; /* Interface finale conservée */
+
+ result = true;
+
+ final = (plugin_interface *)G_PLUGIN_MODULE(plugin)->interface;
+
+ if (final != NULL)
+ {
+ if (final->name != NULL) free(final->name);
+ if (final->desc != NULL) free(final->desc);
+ if (final->version != NULL) free(final->version);
+ if (final->url != NULL) free(final->url);
+
+ assert(final->required_count == 1);
+
+ if (final->required != NULL)
+ free(final->required);
+
+ if (final->actions != NULL)
+ free(final->actions);
+
+ free(final);
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : plugin = greffon à manipuler. *
* action = type d'action attendue. *
* *
* Description : Accompagne la fin du chargement des modules natifs. *
@@ -555,6 +517,103 @@ static void py_plugin_module_notify_plugins_loaded_wrapper(GPluginModule *plugin
/******************************************************************************
* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* args = arguments fournis à l'appel. *
+* *
+* Description : Fournit le nom brut associé au greffon par défaut. *
+* *
+* Retour : Désignation brute du greffon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_plugin_module_get_modname_by_default(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Bilan à retourner */
+ GPluginModule *plugin; /* Version native du greffon */
+ char *path; /* Chemin à traiter */
+
+ plugin = G_PLUGIN_MODULE(pygobject_get(self));
+
+ path = strdup(g_plugin_module_get_filename(plugin));
+
+ result = PyUnicode_FromString(basename(path));
+
+ free(path);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : plugin = greffon à valider. *
+* *
+* Description : Fournit le nom brut associé au greffon. *
+* *
+* Retour : Désignation brute du greffon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *py_plugin_module_get_modname_wrapper(const GPluginModule *plugin)
+{
+ char *result; /* Désignation brute à renvoyer*/
+ PyGILState_STATE gstate; /* Sauvegarde d'environnement */
+ PyObject *pyobj; /* Objet Python concerné */
+ PyObject *pyret; /* Bilan d'exécution */
+
+#define PLUGIN_MODULE_GET_MODNAME_WRAPPER PYTHON_WRAPPER_DEF_WITH \
+( \
+ _get_modname, "$self, /", \
+ METH_VARARGS, py_plugin_module_get_modname_by_default, \
+ "(Abstract) method providing the raw module name of the plugin.\n" \
+ " loaded.\n" \
+ "\n" \
+ "The result should be a short string value.\n" \
+ "\n" \
+ "A default implementation builds the module name from the Python" \
+ " script filename." \
+)
+
+ result = NULL;
+
+ gstate = PyGILState_Ensure();
+
+ pyobj = pygobject_new(G_OBJECT(plugin));
+
+ if (has_python_method(pyobj, "_get_modname"))
+ {
+ pyret = run_python_method(pyobj, "_get_modname", NULL);
+
+ if (!PyUnicode_Check(pyret))
+ g_plugin_module_log_variadic_message(plugin, LMT_ERROR,
+ _("The returned raw name must be a string"));
+
+ else
+ result = strdup(PyUnicode_DATA(pyret));
+
+ Py_XDECREF(pyret);
+
+ }
+
+ Py_DECREF(pyobj);
+
+ PyGILState_Release(gstate);
+
+ return result;
+
+}
+
+
+#ifdef INCLUDE_GTK_SUPPORT
+
+
+/******************************************************************************
+* *
* Paramètres : plugin = greffon à manipuler. *
* action = type d'action attendue. *
* dark = indique une préférence pour la variante foncée. *
@@ -783,6 +842,9 @@ static void py_plugin_module_notify_panel_docking_wrapper(const GPluginModule *p
}
+#endif
+
+
/******************************************************************************
* *
* Paramètres : plugin = greffon à manipuler. *
@@ -1300,262 +1362,6 @@ static void py_plugin_module_detect_external_tools_wrapper(const GPluginModule *
/* ---------------------------------------------------------------------------------- */
-/* INTERFACE INTERNE POUR GREFFONS PYTHON */
-/* ---------------------------------------------------------------------------------- */
-
-
-/* Indique le type défini par la GLib pour le greffon Python. */
-G_DEFINE_TYPE(GPythonPlugin, g_python_plugin, G_TYPE_PLUGIN_MODULE);
-
-
-/******************************************************************************
-* *
-* Paramètres : klass = classe à initialiser. *
-* *
-* Description : Initialise la classe des greffons Python. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_python_plugin_class_init(GPythonPluginClass *klass)
-{
- GObjectClass *object; /* Autre version de la classe */
- GPluginModuleClass *plugin; /* Version parente de la classe*/
-
- object = G_OBJECT_CLASS(klass);
-
- object->dispose = (GObjectFinalizeFunc/* ! */)g_python_plugin_dispose;
- object->finalize = (GObjectFinalizeFunc)g_python_plugin_finalize;
-
- plugin = G_PLUGIN_MODULE_CLASS(klass);
-
- plugin->get_modname = (pg_get_modname_fc)g_python_plugin_get_modname;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : plugin = instance à initialiser. *
-* *
-* Description : Initialise l'instance d'un greffon Python. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_python_plugin_init(GPythonPlugin *plugin)
-{
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : plugin = instance d'objet GLib à traiter. *
-* *
-* Description : Supprime toutes les références externes. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_python_plugin_dispose(GPythonPlugin *plugin)
-{
-#if 0
- PyThreadState *tstate; /* Contexte d'environnement */
-
- /**
- * Cf. https://docs.python.org/3/c-api/init.html#thread-state-and-the-global-interpreter-lock
- *
- * Cependant, comme on se trouve à priori dans le thread principal de l'interpréteur,
- * PyGILState_Ensure() ne pose aucun verrou. Ce qui aboutit à la situation suivante :
- *
- * Fatal Python error: drop_gil: GIL is not locked
- *
- * On peut forcer les choses avec PyEval_AcquireLock(), mais cette fonction est marquée
- * comme dépréciée depuis Python 3.2.
- *
- * Donc on choisit les alternatives officielles.
- *
- * Cependant, PyThreadState_Get() renvoit l'erreur suivante :
- *
- * Fatal Python error: PyThreadState_Get: no current thread
- *
- * Donc on se rabat sur une sauvegarde, qui n'est initialisée que lorsque l'interpréteur
- * est intégré dans l'éditeur.
- */
-
- tstate = get_pychrysalide_main_tstate();
-
- if (tstate != NULL)
- PyEval_RestoreThread(tstate);
-
- if (tstate != NULL)
- PyEval_SaveThread();
-#endif
-
- G_OBJECT_CLASS(g_python_plugin_parent_class)->dispose(G_OBJECT(plugin));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : plugin = instance d'objet GLib à traiter. *
-* *
-* Description : Procède à la libération totale de la mémoire. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_python_plugin_finalize(GPythonPlugin *plugin)
-{
- plugin_interface *final; /* Interface finale conservée */
-
- final = (plugin_interface *)G_PLUGIN_MODULE(plugin)->interface;
-
- if (final != NULL)
- {
- if (final->name != NULL) free(final->name);
- if (final->desc != NULL) free(final->desc);
- if (final->version != NULL) free(final->version);
- if (final->url != NULL) free(final->url);
-
- assert(final->required_count == 1);
-
- if (final->required != NULL)
- free(final->required);
-
- if (final->actions != NULL)
- free(final->actions);
-
- free(final);
-
- }
-
- G_OBJECT_CLASS(g_python_plugin_parent_class)->finalize(G_OBJECT(plugin));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : plugin = greffon à valider. *
-* *
-* Description : Fournit le nom brut associé au greffon. *
-* *
-* Retour : Désignation brute du greffon. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static char *g_python_plugin_get_modname(const GPythonPlugin *plugin)
-{
- char *result; /* Désignation brute à renvoyer*/
- char *path; /* Chemin à traiter */
-
- path = strdup(g_plugin_module_get_filename(G_PLUGIN_MODULE(plugin)));
-
- result = strdup(basename(path));
-
- free(path);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : modname = nom du module à charger. *
-* filename = chemin d'accès au code Python à charger. *
-* *
-* Description : Crée un greffon à partir de code Python. *
-* *
-* Retour : Adresse de la structure mise en place ou NULL si erreur. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-GPluginModule *g_python_plugin_new(const char *modname, const char *filename)
-{
- GPythonPlugin *result; /* Structure à retourner */
- PyObject *name; /* Chemin d'accès pour Python */
- PyObject *module; /* Script Python chargé */
- PyObject *dict; /* Dictionnaire associé */
- PyObject *class; /* Classe à instancier */
- PyObject *instance; /* Instance Python du greffon */
-
- name = PyUnicode_FromString(modname);
- if (name == NULL) goto bad_exit;
-
- module = PyImport_Import(name);
- Py_DECREF(name);
-
- if (module == NULL) goto no_import;
-
- dict = PyModule_GetDict(module);
- class = PyDict_GetItemString(dict, "AutoLoad");
-
- if (class == NULL) goto no_class;
- if (!PyType_Check(class->ob_type)) goto no_class;
-
- instance = PyObject_CallFunction(class, NULL);
- if (instance == NULL) goto no_instance;
-
- result = G_PYTHON_PLUGIN(pygobject_get(instance));
-
- G_PLUGIN_MODULE(result)->filename = strdup(filename);
-
- /**
- * L'instance Python et l'objet GLib résultante sont un même PyGObject.
- *
- * Donc pas besoin de toucher au comptage des références ici, la libération
- * se réalisera à la fin, quand l'objet GLib sera libéré.
- */
-
- Py_DECREF(module);
-
- return G_PLUGIN_MODULE(result);
-
- no_instance:
-
- log_pychrysalide_exception(_("An error occured when building the 'AutoLoad' instance"));
-
- no_class:
-
- if (class == NULL)
- log_plugin_simple_message(LMT_ERROR,
- _("An error occured when looking for the 'AutoLoad': item not found!"));
-
- no_import:
-
- Py_XDECREF(module);
-
- log_pychrysalide_exception(_("An error occured when importing '%s'"), modname);
-
- bad_exit:
-
- return NULL;
-
-}
-
-
-
-/* ---------------------------------------------------------------------------------- */
/* MODULE PYTHON POUR LES SCRIPTS */
/* ---------------------------------------------------------------------------------- */
@@ -1865,9 +1671,12 @@ PyTypeObject *get_python_plugin_module_type(void)
static PyMethodDef py_plugin_module_methods[] = {
PLUGIN_MODULE_MANAGE_WRAPPER,
PLUGIN_MODULE_NOTIFY_PLUGINS_LOADED_WRAPPER,
+ PLUGIN_MODULE_GET_MODNAME_WRAPPER,
+#ifdef INCLUDE_GTK_SUPPORT
PLUGIN_MODULE_INCLUDE_THEME_WRAPPER,
PLUGIN_MODULE_ON_PANEL_CREATION_WRAPPER,
PLUGIN_MODULE_ON_PANEL_DOCKING_WRAPPER,
+#endif
PLUGIN_MODULE_HANDLE_BINARY_CONTENT_WRAPPER,
PLUGIN_MODULE_HANDLE_LOADED_CONTENT_WRAPPER,
PLUGIN_MODULE_HANDLE_BINARY_FORMAT_ANALYSIS_WRAPPER,
@@ -1938,7 +1747,7 @@ bool ensure_python_plugin_module_is_registered(void)
dict = PyModule_GetDict(module);
- if (!register_class_for_pygobject(dict, G_TYPE_PYTHON_PLUGIN, type, &PyGObject_Type))
+ if (!register_class_for_pygobject(dict, G_TYPE_PLUGIN_MODULE, type))
return false;
if (!define_plugin_module_constants(type))
@@ -1949,3 +1758,80 @@ bool ensure_python_plugin_module_is_registered(void)
return true;
}
+
+
+/******************************************************************************
+* *
+* Paramètres : modname = nom du module à charger. *
+* filename = chemin d'accès au code Python à charger. *
+* *
+* Description : Crée un greffon à partir de code Python. *
+* *
+* Retour : Adresse de la structure mise en place ou NULL si erreur. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GPluginModule *create_python_plugin(const char *modname, const char *filename)
+{
+ GPluginModule *result; /* Structure à retourner */
+ PyObject *name; /* Chemin d'accès pour Python */
+ PyObject *module; /* Script Python chargé */
+ PyObject *dict; /* Dictionnaire associé */
+ PyObject *class; /* Classe à instancier */
+ PyObject *instance; /* Instance Python du greffon */
+
+ name = PyUnicode_FromString(modname);
+ if (name == NULL) goto bad_exit;
+
+ module = PyImport_Import(name);
+ Py_DECREF(name);
+
+ if (module == NULL) goto no_import;
+
+ dict = PyModule_GetDict(module);
+ class = PyDict_GetItemString(dict, "AutoLoad");
+
+ if (class == NULL) goto no_class;
+ if (!PyType_Check(class->ob_type)) goto no_class;
+
+ instance = PyObject_CallFunction(class, NULL);
+ if (instance == NULL) goto no_instance;
+
+ result = G_PLUGIN_MODULE(pygobject_get(instance));
+
+ result->filename = strdup(filename);
+
+ /**
+ * L'instance Python et l'objet GLib résultante sont un même PyGObject.
+ *
+ * Donc pas besoin de toucher au comptage des références ici, la libération
+ * se réalisera à la fin, quand l'objet GLib sera libéré.
+ */
+
+ Py_DECREF(module);
+
+ return result;
+
+ no_instance:
+
+ log_pychrysalide_exception(_("An error occured when building the 'AutoLoad' instance"));
+
+ no_class:
+
+ if (class == NULL)
+ log_plugin_simple_message(LMT_ERROR,
+ _("An error occured when looking for the 'AutoLoad': item not found!"));
+
+ no_import:
+
+ Py_XDECREF(module);
+
+ log_pychrysalide_exception(_("An error occured when importing '%s'"), modname);
+
+ bad_exit:
+
+ return NULL;
+
+}