From 55ccf25e0c6666436f0ecd222e60208ebf6ab30e Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Fri, 4 Jan 2019 00:36:47 +0100
Subject: Defined a dynamic type for each plugin.

---
 plugins/arm/core.c                      |    2 +-
 plugins/dalvik/core.c                   |    2 +-
 plugins/devdbg/speed.c                  |    2 +-
 plugins/dex/core.c                      |    2 +-
 plugins/dexbnf/core.c                   |    2 +-
 plugins/dwarf/core.c                    |    2 +-
 plugins/elf/core.c                      |    2 +-
 plugins/itanium/core.c                  |    2 +-
 plugins/javadesc/core.c                 |    2 +-
 plugins/libcsem/semantic.c              |    2 +-
 plugins/lnxsyscalls/core.c              |    2 +-
 plugins/mobicore/core.c                 |    2 +-
 plugins/pychrysalide/Makefile.am        |    1 -
 plugins/pychrysalide/arch/processor.c   |   39 +-
 plugins/pychrysalide/dt.c               |  469 --------------
 plugins/pychrysalide/dt.h               |   47 --
 plugins/pychrysalide/gui/editem.c       |    3 -
 plugins/pychrysalide/gui/panels/panel.c |   39 +-
 plugins/pychrysalide/helpers.c          |   74 +++
 plugins/pychrysalide/helpers.h          |   12 +-
 plugins/pychrysalide/plugin.c           | 1041 ++++++++++++++++++-------------
 plugins/pychrysalide/pychrysa.c         |    5 +-
 plugins/readdex/reader.c                |    2 +-
 plugins/readelf/reader.c                |    2 +-
 plugins/readmc/reader.c                 |    2 +-
 plugins/ropgadgets/plugin.c             |    2 +-
 src/core/core.c                         |    5 +
 src/plugins/Makefile.am                 |    1 +
 src/plugins/dt.c                        |  474 ++++++++++++++
 src/plugins/dt.h                        |   47 ++
 src/plugins/plugin-def.h                |   13 +-
 src/plugins/plugin-int.h                |   16 +-
 src/plugins/plugin.c                    |  396 ++++++++++--
 src/plugins/plugin.h                    |   12 +-
 tests/plugins/__init__.py               |    0
 tests/plugins/plugin.py                 |  223 +++++++
 36 files changed, 1824 insertions(+), 1125 deletions(-)
 delete mode 100644 plugins/pychrysalide/dt.c
 delete mode 100644 plugins/pychrysalide/dt.h
 create mode 100644 src/plugins/dt.c
 create mode 100644 src/plugins/dt.h
 create mode 100644 tests/plugins/__init__.py
 create mode 100644 tests/plugins/plugin.py

diff --git a/plugins/arm/core.c b/plugins/arm/core.c
index d2dd805..07b9b24 100644
--- a/plugins/arm/core.c
+++ b/plugins/arm/core.c
@@ -32,7 +32,7 @@
 
 
 
-DEFINE_CHRYSALIDE_PLUGIN("arm", "Add support for the ARM architecture", "0.1.0",
+DEFINE_CHRYSALIDE_PLUGIN("GArmPlugin", "arm", "Add support for the ARM architecture", "0.1.0",
                          RL("PyChrysalide"), AL(PGA_PLUGIN_INIT, PGA_PLUGIN_EXIT));
 
 
diff --git a/plugins/dalvik/core.c b/plugins/dalvik/core.c
index 2e936b9..d7e5a04 100644
--- a/plugins/dalvik/core.c
+++ b/plugins/dalvik/core.c
@@ -35,7 +35,7 @@
 
 
 
-DEFINE_CHRYSALIDE_PLUGIN("dalvik", "Add support for the Dalvik architecture", "0.1.0",
+DEFINE_CHRYSALIDE_PLUGIN("GDalvikPlugin", "dalvik", "Add support for the Dalvik architecture", "0.1.0",
                          RL("PyChrysalide"), AL(PGA_PLUGIN_INIT, PGA_PLUGIN_EXIT));
 
 
diff --git a/plugins/devdbg/speed.c b/plugins/devdbg/speed.c
index 935fbd9..77c407a 100644
--- a/plugins/devdbg/speed.c
+++ b/plugins/devdbg/speed.c
@@ -38,7 +38,7 @@
 
 
 
-DEFINE_CHRYSALIDE_ACTIVE_PLUGIN("Speed Measure", "Tracks to time spent for disassembling code", "0.1.0",
+DEFINE_CHRYSALIDE_ACTIVE_PLUGIN("GSpeedPlugin", "Speed Measure", "Tracks to time spent for disassembling code", "0.1.0",
                                 PGA_FORMAT_ANALYSIS_STARTED,PGA_FORMAT_ANALYSIS_ENDED,
                                 PGA_FORMAT_POST_ANALYSIS_STARTED, PGA_FORMAT_POST_ANALYSIS_ENDED,
                                 PGA_DISASSEMBLY_STARTED, PGA_DISASSEMBLY_ENDED);
diff --git a/plugins/dex/core.c b/plugins/dex/core.c
index 6bdb9d5..3e5b835 100644
--- a/plugins/dex/core.c
+++ b/plugins/dex/core.c
@@ -33,7 +33,7 @@
 
 
 
-DEFINE_CHRYSALIDE_PLUGIN("dex", "Add support for the DEX format", "0.1.0",
+DEFINE_CHRYSALIDE_PLUGIN("GDexPlugin", "dex", "Add support for the DEX format", "0.1.0",
                          RL("PyChrysalide", "dexbnf"), AL(PGA_PLUGIN_INIT, PGA_CONTENT_RESOLVER));
 
 
diff --git a/plugins/dexbnf/core.c b/plugins/dexbnf/core.c
index 774e88e..736fa5f 100644
--- a/plugins/dexbnf/core.c
+++ b/plugins/dexbnf/core.c
@@ -33,7 +33,7 @@
 
 
 
-DEFINE_CHRYSALIDE_PLUGIN("dexbnf", "Symbol demangler for Dex", "0.1.0",
+DEFINE_CHRYSALIDE_PLUGIN("GDexBnfPlugin", "dexbnf", "Symbol demangler for Dex", "0.1.0",
                          RL("PyChrysalide"), AL(PGA_PLUGIN_INIT));
 
 
diff --git a/plugins/dwarf/core.c b/plugins/dwarf/core.c
index fa7e0ec..1e2d900 100644
--- a/plugins/dwarf/core.c
+++ b/plugins/dwarf/core.c
@@ -31,7 +31,7 @@
 
 
 
-DEFINE_CHRYSALIDE_PLUGIN("dwarf", "Add support for the DWARF format", "0.1.0",
+DEFINE_CHRYSALIDE_PLUGIN("GDwarfPlugin", "dwarf", "Add support for the DWARF format", "0.1.0",
                          RL("PyChrysalide"), AL(PGA_PLUGIN_INIT, PGA_FORMAT_ATTACH_DEBUG));
 
 
diff --git a/plugins/elf/core.c b/plugins/elf/core.c
index 6b7810e..d3d226e 100644
--- a/plugins/elf/core.c
+++ b/plugins/elf/core.c
@@ -33,7 +33,7 @@
 
 
 
-DEFINE_CHRYSALIDE_PLUGIN("elf", "Add support for the ELF format", "0.1.0",
+DEFINE_CHRYSALIDE_PLUGIN("GElfPlugin", "elf", "Add support for the ELF format", "0.1.0",
                          RL("PyChrysalide"), AL(PGA_PLUGIN_INIT, PGA_CONTENT_RESOLVER));
 
 
diff --git a/plugins/itanium/core.c b/plugins/itanium/core.c
index ecfd7f0..71816f7 100644
--- a/plugins/itanium/core.c
+++ b/plugins/itanium/core.c
@@ -33,7 +33,7 @@
 
 
 
-DEFINE_CHRYSALIDE_PLUGIN("itanium", "Symbol demangler for Itanium", "0.1.0",
+DEFINE_CHRYSALIDE_PLUGIN("GItaniumPlugin", "itanium", "Symbol demangler for Itanium", "0.1.0",
                          RL("PyChrysalide"), AL(PGA_PLUGIN_INIT));
 
 
diff --git a/plugins/javadesc/core.c b/plugins/javadesc/core.c
index e374749..41c4789 100644
--- a/plugins/javadesc/core.c
+++ b/plugins/javadesc/core.c
@@ -33,7 +33,7 @@
 
 
 
-DEFINE_CHRYSALIDE_PLUGIN("javadesc", "Symbol demangler for Java", "0.1.0",
+DEFINE_CHRYSALIDE_PLUGIN("GJavaDescPlugin", "javadesc", "Symbol demangler for Java", "0.1.0",
                          RL("PyChrysalide"), AL(PGA_PLUGIN_INIT));
 
 
diff --git a/plugins/libcsem/semantic.c b/plugins/libcsem/semantic.c
index 0dc330e..de87012 100644
--- a/plugins/libcsem/semantic.c
+++ b/plugins/libcsem/semantic.c
@@ -32,7 +32,7 @@
 
 
 
-DEFINE_CHRYSALIDE_ACTIVE_PLUGIN("LibC semantics", "Register semantic information relative to the libc", "0.1.0",
+DEFINE_CHRYSALIDE_ACTIVE_PLUGIN("GCSemPlugin", "LibC semantics", "Register semantic information relative to the libc", "0.1.0",
                                 PGA_DISASSEMBLY_HOOKED_POST);
 
 
diff --git a/plugins/lnxsyscalls/core.c b/plugins/lnxsyscalls/core.c
index f28e776..cd9fa0e 100644
--- a/plugins/lnxsyscalls/core.c
+++ b/plugins/lnxsyscalls/core.c
@@ -37,7 +37,7 @@
 
 
 
-DEFINE_CHRYSALIDE_PLUGIN("Linux System Calls", "Describes each Linux system call with its arguments", \
+DEFINE_CHRYSALIDE_PLUGIN("GLnxSyscallsPlugin", "Linux System Calls", "Describes each Linux system call with its arguments", \
                          "0.1.0", EMPTY_PG_LIST(.required), AL(PGA_PLUGIN_INIT, PGA_DISASSEMBLY_ENDED));
 
 
diff --git a/plugins/mobicore/core.c b/plugins/mobicore/core.c
index bc7298f..9de116d 100644
--- a/plugins/mobicore/core.c
+++ b/plugins/mobicore/core.c
@@ -32,7 +32,7 @@
 
 
 
-DEFINE_CHRYSALIDE_PLUGIN("mobicore", "Support MobiCore file format for Trusted Applications", "0.1.0",
+DEFINE_CHRYSALIDE_PLUGIN("GMobicorePlugin", "mobicore", "Support MobiCore file format for Trusted Applications", "0.1.0",
                          EMPTY_PG_LIST(.required), AL(PGA_CONTENT_RESOLVER));
 
 
diff --git a/plugins/pychrysalide/Makefile.am b/plugins/pychrysalide/Makefile.am
index 3fe13af..d9194b9 100644
--- a/plugins/pychrysalide/Makefile.am
+++ b/plugins/pychrysalide/Makefile.am
@@ -7,7 +7,6 @@ libdir = $(pluginslibdir)
 pychrysalide_la_SOURCES =				\
 	access.h access.c					\
 	constval.h constval.c				\
-	dt.h dt.c							\
 	helpers.h helpers.c					\
 	plugin.h plugin.c					\
 	pychrysa.h pychrysa.c				\
diff --git a/plugins/pychrysalide/arch/processor.c b/plugins/pychrysalide/arch/processor.c
index 115f980..4feaa8b 100644
--- a/plugins/pychrysalide/arch/processor.c
+++ b/plugins/pychrysalide/arch/processor.c
@@ -31,6 +31,7 @@
 
 #include <i18n.h>
 #include <arch/processor-int.h>
+#include <plugins/dt.h>
 
 
 #include "context.h"
@@ -38,7 +39,6 @@
 #include "instruction.h"
 #include "vmpa.h"
 #include "../access.h"
-#include "../dt.h"
 #include "../helpers.h"
 #include "../analysis/content.h"
 #include "../format/executable.h"
@@ -140,18 +140,16 @@ static bool define_python_arch_processor_constants(PyTypeObject *);
 static PyObject *py_arch_processor_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
     PyObject *result;                       /* Objet à retourner           */
-    bool abstract;                          /* Validation du type parent   */
+    PyTypeObject *base;                     /* Type de base à dériver      */
+    bool first_time;                        /* Evite les multiples passages*/
     GType gtype;                            /* Nouveau type de processeur  */
-    PyObject *sys_mod_dict;                 /* Dictionnaire des modules    */
-    PyObject *modname;                      /* Nom du module du type       */
-    PyObject *module;                       /* Module à recompléter        */
-    PyObject *dict;                         /* Dictionnaire dudit module   */
+    bool status;                            /* Bilan d'un enregistrement   */
 
     /* Validations diverses */
 
-    abstract = (type == get_python_arch_processor_type());
+    base = get_python_arch_processor_type();
 
-    if (abstract)
+    if (type == base)
     {
         result = NULL;
         PyErr_Format(PyExc_RuntimeError, _("%s is an abstract class"), type->tp_name);
@@ -160,30 +158,23 @@ static PyObject *py_arch_processor_new(PyTypeObject *type, PyObject *args, PyObj
 
     /* Mise en place d'un type dédié */
 
-    gtype = built_dynamic_type(G_TYPE_ARCH_PROCESSOR, type->tp_name,
-                               (GClassInitFunc)py_arch_processor_init_gclass);
-
-    /* Enregistrement du nouveau GType dans Python */
-
-    sys_mod_dict = PyImport_GetModuleDict();
+    first_time = (g_type_from_name(type->tp_name) == 0);
 
-    modname = PyDict_GetItemString(type->tp_dict, "__module__");
-
-    module = PyObject_GetItem(sys_mod_dict, modname);
+    gtype = built_dynamic_type(G_TYPE_ARCH_PROCESSOR, type->tp_name,
+                               (GClassInitFunc)py_arch_processor_init_gclass, NULL);
 
-    dict = PyModule_GetDict(module);
+    if (first_time)
+        status = register_class_for_dynamic_pygobject(gtype, type, base);
+    else
+        status = true;
 
-    if (!_register_class_for_pygobject(dict, gtype, type,
-                                       &PyGObject_Type, get_python_arch_processor_type(), NULL))
+    if (!status)
     {
         result = NULL;
         goto exit;
     }
 
-    Py_DECREF(module);
-    Py_DECREF(modname);
-
-    /* On créé, et on laisse ensuite la main à PyGObject_Type.tp_init() */
+    /* On crée, et on laisse ensuite la main à PyGObject_Type.tp_init() */
 
     result = PyType_GenericNew(type, args, kwds);
 
diff --git a/plugins/pychrysalide/dt.c b/plugins/pychrysalide/dt.c
deleted file mode 100644
index 0b46b45..0000000
--- a/plugins/pychrysalide/dt.c
+++ /dev/null
@@ -1,469 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * dt.c - possibilité de créer de nouveaux types de façon dynamique
- *
- * Copyright (C) 2018 Cyrille Bagard
- *
- *  This file is part of Chrysalide.
- *
- *  Chrysalide is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 3 of the License, or
- *  (at your option) any later version.
- *
- *  Chrysalide is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with Chrysalide.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#include "dt.h"
-
-
-#include <assert.h>
-#include <malloc.h>
-
-
-
-/* ------------------------- MODULE DE GESTION DES NOUVEAUX ------------------------- */
-
-
-#define G_TYPE_DYNAMIC_TYPES            g_dynamic_types_get_type()
-#define G_DYNAMIC_TYPES(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_DYNAMIC_TYPES, GDynamicTypes))
-#define G_IS_DYNAMIC_TYPES(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_DYNAMIC_TYPES))
-#define G_DYNAMIC_TYPES_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_DYNAMIC_TYPES, GDynamicTypesClass))
-#define G_IS_DYNAMIC_TYPES_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_DYNAMIC_TYPES))
-#define G_DYNAMIC_TYPES_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DYNAMIC_TYPES, GDynamicTypesClass))
-
-
-/* Mémorisation des caractéristiques de type */
-typedef struct _type_dyn_info_t
-{
-    GType type;                             /* Identifiant unique obtenu   */
-    GClassInitFunc init;                    /* Définition des méthodes     */
-
-} type_dyn_info_t;
-
-/* Description de fichier binaire (instance) */
-typedef struct _GDynamicTypes
-{
-    GObject parent;                         /* A laisser en premier        */
-
-    type_dyn_info_t **info;                 /* Liste d'informations utiles */
-    size_t count;                           /* Taille de cette liste       */
-
-} GDynamicTypes;
-
-/* Description de fichier binaire (classe) */
-typedef struct _GDynamicTypesClass
-{
-    GObjectClass parent;                    /* A laisser en premier        */
-
-} GDynamicTypesClass;
-
-
-/* Indique le type défini pour une gestion de types dynamique. */
-static GType g_dynamic_types_get_type(void);
-
-/* Initialise la classe de gestion de types dynamique. */
-static void g_dynamic_types_class_init(GDynamicTypesClass *);
-
-/* Initialise une gestion de types dynamique. */
-static void g_dynamic_types_init(GDynamicTypes *);
-
-/* Procède à l'initialisation de l'interface de typage nouveau. */
-static void g_dynamic_types_interface_init(GTypePluginClass *);
-
-/* Supprime toutes les références externes. */
-static void g_dynamic_types_dispose(GDynamicTypes *);
-
-/* Procède à la libération totale de la mémoire. */
-static void g_dynamic_types_finalize(GDynamicTypes *);
-
-/* Crée un nouveau gestionnaire de nouveaux types. */
-static GDynamicTypes *g_dynamic_types_new(void);
-
-/* Marque une augmentation des utilisations. */
-static void g_dynamic_types_use(GDynamicTypes *);
-
-/* Marque une diminution des utilisations. */
-static void g_dynamic_types_unuse(GDynamicTypes *);
-
-/* Complète la définition d'un type dynamiquement. */
-static void g_dynamic_types_complete_type(GDynamicTypes *, GType, GTypeInfo *, GTypeValueTable *);
-
-/* Retrouve les informations concernant un type dynamique. */
-static const type_dyn_info_t *g_dynamic_types_find(const GDynamicTypes *, GType);
-
-/* Fournit un identifiant GLib pour un nouveau type Python. */
-static GType g_dynamic_types_register_type(GDynamicTypes *, GType, const char *, GClassInitFunc);
-
-
-
-/* ----------------------- ACCOMPAGNEMENTS DES NOUVEAUX TYPES ----------------------- */
-
-
-/* Encadrement des nouveaux types Python dérivés */
-static GDynamicTypes *_python_dtypes = NULL;
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/*                           MODULE DE GESTION DES NOUVEAUX                           */
-/* ---------------------------------------------------------------------------------- */
-
-/* Indique le type défini pour une gestion de types dynamique. */
-G_DEFINE_TYPE_WITH_CODE(GDynamicTypes, g_dynamic_types, G_TYPE_OBJECT,
-                        G_IMPLEMENT_INTERFACE(G_TYPE_TYPE_PLUGIN, g_dynamic_types_interface_init));
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : klass = classe à initialiser.                                *
-*                                                                             *
-*  Description : Initialise la classe de gestion de types dynamique.          *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void g_dynamic_types_class_init(GDynamicTypesClass *klass)
-{
-    GObjectClass *object;                   /* Autre version de la classe  */
-
-    object = G_OBJECT_CLASS(klass);
-
-    object->dispose = (GObjectFinalizeFunc/* ! */)g_dynamic_types_dispose;
-    object->finalize = (GObjectFinalizeFunc)g_dynamic_types_finalize;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : types = instance à initialiser.                              *
-*                                                                             *
-*  Description : Initialise une gestion de types dynamique.                   *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void g_dynamic_types_init(GDynamicTypes *types)
-{
-
-}
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : iface = interface GLib à initialiser.                        *
-*                                                                             *
-*  Description : Procède à l'initialisation de l'interface de typage nouveau. *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void g_dynamic_types_interface_init(GTypePluginClass *iface)
-{
-    iface->use_plugin = (GTypePluginUse)g_dynamic_types_use;
-    iface->unuse_plugin = (GTypePluginUnuse)g_dynamic_types_unuse;
-    iface->complete_type_info = (GTypePluginCompleteTypeInfo)g_dynamic_types_complete_type;
-
-}
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : types = instance d'objet GLib à traiter.                     *
-*                                                                             *
-*  Description : Supprime toutes les références externes.                     *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void g_dynamic_types_dispose(GDynamicTypes *types)
-{
-    G_OBJECT_CLASS(g_dynamic_types_parent_class)->dispose(G_OBJECT(types));
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : types = instance d'objet GLib à traiter.                     *
-*                                                                             *
-*  Description : Procède à la libération totale de la mémoire.                *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void g_dynamic_types_finalize(GDynamicTypes *types)
-{
-    G_OBJECT_CLASS(g_dynamic_types_parent_class)->finalize(G_OBJECT(types));
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : -                                                            *
-*                                                                             *
-*  Description : Crée un nouveau gestionnaire de nouveaux types.              *
-*                                                                             *
-*  Retour      : Instance mise en place.                                      *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static GDynamicTypes *g_dynamic_types_new(void)
-{
-    GDynamicTypes *result;                  /* Adresse à retourner         */
-
-    result = g_object_new(G_TYPE_DYNAMIC_TYPES, NULL);
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : types = gestionnaire de types courant.                       *
-*                                                                             *
-*  Description : Marque une augmentation des utilisations.                    *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void g_dynamic_types_use(GDynamicTypes *types)
-{
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : types = gestionnaire de types courant.                       *
-*                                                                             *
-*  Description : Marque une diminution des utilisations.                      *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void g_dynamic_types_unuse(GDynamicTypes *types)
-{
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : types = gestionnaire de types courant.                       *
-*                type  = nouveau type GLib à traiter.                         *
-*                info  = information concernant ce type à constituer. [OUT]   *
-*                table = table de valeur à éventuellement initialiser. [OUT]  *
-*                                                                             *
-*  Description : Complète la définition d'un type dynamiquement.              *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void g_dynamic_types_complete_type(GDynamicTypes *types, GType type, GTypeInfo *info, GTypeValueTable *table)
-{
-    const type_dyn_info_t *nfo;             /* Source d'inspiration        */
-    GType parent;                           /* Type parent du type         */
-    GTypeQuery query;                       /* Informations complémentaires*/
-
-    /* Consultation */
-
-    nfo = g_dynamic_types_find(types, type);
-    assert(nfo != NULL);
-
-    parent = g_type_parent(type);
-    g_type_query(parent, &query);
-
-    /* Définition */
-
-    info->class_size = query.class_size;
-    info->class_init = nfo->init;
-
-    info->instance_size = query.instance_size;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : parent = type GLib parent.                                   *
-*                type   = identifiant du type GLib à considérer.              *
-*                                                                             *
-*  Description : Retrouve les informations concernant un type dynamique.      *
-*                                                                             *
-*  Retour      : Structure contenant les informations associées au type.      *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static const type_dyn_info_t *g_dynamic_types_find(const GDynamicTypes *types, GType target)
-{
-    type_dyn_info_t *result;                /* Informations à retourner    */
-    size_t i;                               /* Boucle de parcours          */
-
-    result = NULL;
-
-    for (i = 0; i < types->count && result == NULL; i++)
-        if (types->info[i]->type == target)
-            result = types->info[i];
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : parent = type GLib parent.                                   *
-*                name   = désignation du nouveau type.                        *
-*                init   = procédure d'initialisation de la classe associée.   *
-*                                                                             *
-*  Description : Fournit un identifiant GLib pour un nouveau type Python.     *
-*                                                                             *
-*  Retour      : identifiant d'un nouveau type valide, ou 0.                  *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static GType g_dynamic_types_register_type(GDynamicTypes *types, GType parent, const char *name, GClassInitFunc init)
-{
-    GType result;                           /* Identifiant à retourner     */
-    type_dyn_info_t *new;                   /* Mémorisation de paramètres  */
-
-    /* Création d'un nouveau type adapté */
-
-    result = g_type_register_dynamic(parent, name, G_TYPE_PLUGIN(types), 0);
-
-    if (result == 0)
-        goto exit;
-
-    new = malloc(sizeof(type_dyn_info_t));
-
-    new->type = result;
-    new->init = init;
-
-    /* Inscription définitive */
-
-    types->info = realloc(types->info, ++types->count * sizeof(type_dyn_info_t *));
-
-    types->info[types->count - 1] = new;
-
- exit:
-
-    return result;
-
-}
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/*                         ACCOMPAGNEMENTS DES NOUVEAUX TYPES                         */
-/* ---------------------------------------------------------------------------------- */
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : -                                                            *
-*                                                                             *
-*  Description : Lance le support de dérivations de types dans Python.        *
-*                                                                             *
-*  Retour      : Bilan de l'opération.                                        *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-bool init_dynamic_python_types(void)
-{
-    bool result;                            /* Bilan à retourner           */
-
-    _python_dtypes = g_dynamic_types_new();
-
-    result = (_python_dtypes != NULL);
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : -                                                            *
-*                                                                             *
-*  Description : Arrête le support de dérivations de types dans Python.       *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-void exit_dynamic_python_types(void)
-{
-    g_object_unref(G_OBJECT(_python_dtypes));
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : parent = type GLib parent.                                   *
-*                name   = désignation du nouveau type.                        *
-*                init   = procédure d'initialisation de la classe associée.   *
-*                                                                             *
-*  Retour      : Identifiant d'un nouveau type valide, ou 0.                  *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-GType built_dynamic_type(GType parent, const char *name, GClassInitFunc init)
-{
-    GType result;                           /* Identifiant à retourner     */
-
-    result = g_type_from_name(name);
-
-    if (result == 0)
-        result = g_dynamic_types_register_type(_python_dtypes, parent, name, init);
-
-    return result;
-
-}
diff --git a/plugins/pychrysalide/dt.h b/plugins/pychrysalide/dt.h
deleted file mode 100644
index b0f16db..0000000
--- a/plugins/pychrysalide/dt.h
+++ /dev/null
@@ -1,47 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * dt.h - prototypes pour la possibilité de créer de nouveaux types de façon dynamique
- *
- * Copyright (C) 2018 Cyrille Bagard
- *
- *  This file is part of Chrysalide.
- *
- *  Chrysalide is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 3 of the License, or
- *  (at your option) any later version.
- *
- *  Chrysalide is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with Chrysalide.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#ifndef _PLUGINS_PYCHRYSALIDE_DT_H
-#define _PLUGINS_PYCHRYSALIDE_DT_H
-
-
-#include <glib-object.h>
-#include <stdbool.h>
-
-
-
-/* ----------------------- ACCOMPAGNEMENTS DES NOUVEAUX TYPES ----------------------- */
-
-
-/* Lance le support de dérivations de types dans Python. */
-bool init_dynamic_python_types(void);
-
-/* Arrête le support de dérivations de types dans Python. */
-void exit_dynamic_python_types(void);
-
-/* Fournit un identifiant GLib pour un nouveau type Python. */
-GType built_dynamic_type(GType, const char *, GClassInitFunc);
-
-
-
-#endif  /* _PLUGINS_PYCHRYSALIDE_DT_H */
diff --git a/plugins/pychrysalide/gui/editem.c b/plugins/pychrysalide/gui/editem.c
index 986d1cb..68962ae 100644
--- a/plugins/pychrysalide/gui/editem.c
+++ b/plugins/pychrysalide/gui/editem.c
@@ -45,9 +45,6 @@
 /* Réagit à un changement de contenu chargé en cours d'analyse. */
 static void py_editor_item_change_content_wrapper(GEditorItem *, GLoadedContent *, GLoadedContent *);
 
-/* Réagit à un changement de contenu chargé en cours d'analyse. */
-static void py_editor_item_change_content_wrapper(GEditorItem *, GLoadedContent *, GLoadedContent *);
-
 /* Réagit à un changement de vue du contenu en cours d'analyse. */
 static void py_editor_item_change_view_wrapper(GEditorItem *, GLoadedPanel *, GLoadedPanel *);
 
diff --git a/plugins/pychrysalide/gui/panels/panel.c b/plugins/pychrysalide/gui/panels/panel.c
index 1df0670..d4062d3 100644
--- a/plugins/pychrysalide/gui/panels/panel.c
+++ b/plugins/pychrysalide/gui/panels/panel.c
@@ -32,11 +32,11 @@
 #include <core/params.h>
 #include <gui/core/panels.h>
 #include <gui/panels/panel-int.h>
+#include <plugins/dt.h>
 
 
 #include "../editem.h"
 #include "../../access.h"
-#include "../../dt.h"
 #include "../../helpers.h"
 #include "../../gtkext/dockable.h"
 
@@ -89,18 +89,16 @@ static bool py_panel_item_define_constants(PyTypeObject *);
 static PyObject *py_panel_item_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
     PyObject *result;                       /* Objet à retourner           */
-    bool abstract;                          /* Validation du type parent   */
+    PyTypeObject *base;                     /* Type de base à dériver      */
+    bool first_time;                        /* Evite les multiples passages*/
     GType gtype;                            /* Nouveau type de processeur  */
-    PyObject *sys_mod_dict;                 /* Dictionnaire des modules    */
-    PyObject *modname;                      /* Nom du module du type       */
-    PyObject *module;                       /* Module à recompléter        */
-    PyObject *dict;                         /* Dictionnaire dudit module   */
+    bool status;                            /* Bilan d'un enregistrement   */
 
     /* Validations diverses */
 
-    abstract = (type == get_python_panel_item_type());
+    base = get_python_panel_item_type();
 
-    if (abstract)
+    if (type == base)
     {
         result = NULL;
         PyErr_Format(PyExc_RuntimeError, _("%s is an abstract class"), type->tp_name);
@@ -109,30 +107,23 @@ static PyObject *py_panel_item_new(PyTypeObject *type, PyObject *args, PyObject
 
     /* Mise en place d'un type dédié */
 
-    gtype = built_dynamic_type(G_TYPE_PANEL_ITEM, type->tp_name,
-                               (GClassInitFunc)py_panel_item_init_gclass);
-
-    /* Enregistrement du nouveau GType dans Python */
-
-    sys_mod_dict = PyImport_GetModuleDict();
+    first_time = (g_type_from_name(type->tp_name) == 0);
 
-    modname = PyDict_GetItemString(type->tp_dict, "__module__");
-
-    module = PyObject_GetItem(sys_mod_dict, modname);
+    gtype = built_dynamic_type(G_TYPE_PANEL_ITEM, type->tp_name,
+                               (GClassInitFunc)py_panel_item_init_gclass, NULL);
 
-    dict = PyModule_GetDict(module);
+    if (first_time)
+        status = register_class_for_dynamic_pygobject(gtype, type, base);
+    else
+        status = true;
 
-    if (!_register_class_for_pygobject(dict, gtype, type,
-                                       &PyGObject_Type, get_python_panel_item_type(), NULL))
+    if (!status)
     {
         result = NULL;
         goto exit;
     }
 
-    Py_DECREF(module);
-    Py_DECREF(modname);
-
-    /* On créé, et on laisse ensuite la main à PyGObject_Type.tp_init() */
+    /* On crée, et on laisse ensuite la main à PyGObject_Type.tp_init() */
 
     result = PyType_GenericNew(type, args, kwds);
 
diff --git a/plugins/pychrysalide/helpers.c b/plugins/pychrysalide/helpers.c
index ad62de4..a930097 100644
--- a/plugins/pychrysalide/helpers.c
+++ b/plugins/pychrysalide/helpers.c
@@ -701,3 +701,77 @@ bool _register_class_for_pygobject(PyObject *dict, GType gtype, PyTypeObject *ty
     return result;
 
 }
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : dict  = dictionnaire où conserver une référence au type créé.*
+*                gtype = type dans sa version GLib.                           *
+*                type  = type dans sa version Python.                         *
+*                base  = type de base de l'objet.                             *
+*                                                                             *
+*  Description : Enregistre un type Python dérivant d'un type GLib dynamique. *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool register_class_for_dynamic_pygobject(GType gtype, PyTypeObject *type, PyTypeObject *base)
+{
+    bool result;                            /* Bilan à retourner           */
+    PyTypeObject *legacy_parent;            /* Type parent d'origine       */
+    PyObject *sys_mod_dict;                 /* Dictionnaire des modules    */
+    PyObject *modname;                      /* Nom du module du type       */
+    PyObject *module;                       /* Module à recompléter        */
+    PyObject *dict;                         /* Dictionnaire dudit module   */
+
+    /**
+     * Lors de l'appel à pygobject_register_class(), PyGObject remplace systématiquement
+     * le type Python fourni par :
+     *
+     *    Py_TYPE(type) = PyGObject_MetaType;
+     *
+     * Ce nouveau type est le suivant (cf. gi/types.py) :
+     *
+     *    class _GObjectMetaBase(type):
+     *        """Metaclass for automatically registering GObject classes."""
+     *
+     * D'une part, comme les enregistrements sont gérés manuellement dans le cas de
+     * types dérivés dynamiquement d'objets natifs, ce changement est inutile.
+     *
+     * D'autre part, il semble avoir un soucis de références (cf. testGarbageCollecting()
+     * du fichier de test plugins/plugin.py) :
+     *
+     *    python3dm: ../Modules/gcmodule.c:379: visit_decref: Assertion `_PyGCHead_REFS(gc) != 0' failed.
+     *
+     *    #3  __GI___assert_fail ()
+     *    #4  visit_decref ()
+     *    #5  subtype_traverse ()
+     *    #6  subtract_refs ()
+     *    #7  collect ()
+     *    #8  collect_with_callback ()
+     *    #9  gc_collect ()
+     *
+     * On restaure donc le type d'origine de l'objet Python créé dynamquement pour éviter
+     * ce genre de soucis.
+     */
+
+    legacy_parent = Py_TYPE(type);
+
+    sys_mod_dict = PyImport_GetModuleDict();
+
+    modname = PyDict_GetItemString(type->tp_dict, "__module__");
+
+    module = PyObject_GetItem(sys_mod_dict, modname);
+
+    dict = PyModule_GetDict(module);
+
+    result = _register_class_for_pygobject(dict, gtype, type, &PyGObject_Type, base, NULL);
+
+    Py_TYPE(type) = legacy_parent;
+
+    return result;
+
+}
diff --git a/plugins/pychrysalide/helpers.h b/plugins/pychrysalide/helpers.h
index e080ca4..bf95e61 100644
--- a/plugins/pychrysalide/helpers.h
+++ b/plugins/pychrysalide/helpers.h
@@ -25,8 +25,9 @@
 #define _PLUGINS_PYCHRYSALIDE_HELPERS_H
 
 
-#include <glib-object.h>
 #include <Python.h>
+#include <assert.h>
+#include <glib-object.h>
 #include <stdbool.h>
 
 
@@ -97,13 +98,8 @@ bool _register_class_for_pygobject(PyObject *, GType, PyTypeObject *, PyTypeObje
 #define register_class_for_pygobject(dict, gtype, type, base) \
     _register_class_for_pygobject(dict, gtype, type, base, NULL)
 
-
-/**
- * Quand on remplace un objet GLib dans le dos de Python, il faut
- * le remplacer de la même manière qu'on l'a obtenu !
- */
-
-#define pygobject_set(p, v) ((PyGObject *)(p))->obj = (GObject *)v
+/* Enregistre un type Python dérivant d'un type GLib dynamique. */
+bool register_class_for_dynamic_pygobject(GType, PyTypeObject *, PyTypeObject *);
 
 
 
diff --git a/plugins/pychrysalide/plugin.c b/plugins/pychrysalide/plugin.c
index a693d7b..22bfabb 100644
--- a/plugins/pychrysalide/plugin.c
+++ b/plugins/pychrysalide/plugin.c
@@ -32,6 +32,7 @@
 
 
 #include <common/extstr.h>
+#include <plugins/dt.h>
 #include <plugins/plugin-int.h>
 
 
@@ -41,6 +42,50 @@
 
 
 
+/* ------------------------ 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);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_plugin_module_init(PyObject *self, PyObject *args, PyObject *kwds);
+
+/* Valide les fonctionnalités déclarées en actions. */
+static bool py_plugin_module_check_interface(PyObject *);
+
+/* Accompagne la fin du chargement des modules natifs. */
+static void py_plugin_module_notify_native_loaded_wrapper(GPluginModule *, PluginAction);
+
+/* Complète une liste de resources pour thème. */
+static void py_plugin_module_include_theme_wrapper(const GPluginModule *, PluginAction, char ***, size_t *);
+
+/* 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 *);
+
+/* Procède à une opération liée à un contenu chargé. */
+static void py_plugin_module_handle_loaded_content_wrapper(const GPluginModule *, PluginAction, GLoadedContent *, wgroup_id_t, GtkStatusStack *);
+
+/* Procède à une opération liée à l'analyse d'un format. */
+static bool py_plugin_module_handle_binary_format_analysis_wrapper(const GPluginModule *, PluginAction, GBinFormat *, wgroup_id_t, GtkStatusStack *);
+
+/* Procède à un préchargement de format de fichier. */
+static bool py_plugin_module_preload_binary_format_wrapper(const GPluginModule *, PluginAction, GBinFormat *, GPreloadInfo *, GtkStatusStack *);
+
+/* Procède au rattachement d'éventuelles infos de débogage. */
+static void py_plugin_module_attach_debug_format_wrapper(const GPluginModule *, PluginAction, GExeFormat *);
+
+/* Exécute une action pendant un désassemblage de binaire. */
+static void py_plugin_module_process_disassembly_event_wrapper(const GPluginModule *, PluginAction, GLoadedBinary *, GtkStatusStack *, GProcContext *);
+
+/* Effectue la détection d'effets d'outils externes. */
+static void py_plugin_module_detect_external_tools_wrapper(const GPluginModule *, PluginAction, const GLoadedContent *, bool, char ***, size_t *);
+
+
+
 /* --------------------- INTERFACE INTERNE POUR GREFFONS PYTHON --------------------- */
 
 
@@ -75,30 +120,6 @@ 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 *);
 
-/* Reconstruit la déclaration d'interface à partir de lectures. */
-static bool g_python_plugin_read_interface(GPythonPlugin *);
-
-/* Procède à l'initialisation du greffon. */
-static bool g_python_plugin_do_init(GPythonPlugin *);
-
-/* Procède à l'extinction du greffon. */
-static bool g_python_plugin_do_exit(GPythonPlugin *);
-
-/* Procède à une opération liée à un contenu binaire. */
-static void g_python_plugin_handle_binary_content(const GPythonPlugin *, PluginAction, GBinContent *, wgroup_id_t, GtkStatusStack *);
-
-/* Procède à une opération liée à l'analyse d'un format. */
-static bool g_python_plugin_handle_binary_format_analysis(const GPythonPlugin *, PluginAction, GBinFormat *, wgroup_id_t, GtkStatusStack *);
-
-/* Procède à un préchargement de format de fichier. */
-static bool g_python_plugin_preload_binary_format(const GPythonPlugin *, PluginAction, GBinFormat *, GPreloadInfo *, GtkStatusStack *);
-
-/* Procède au rattachement d'éventuelles infos de débogage. */
-static void g_python_plugin_attach_debug_format(const GPythonPlugin *, PluginAction, GExeFormat *);
-
-/* Exécute une action pendant un désassemblage de binaire. */
-static void g_python_plugin_process_disass(const GPythonPlugin *, PluginAction, GLoadedBinary *, GtkStatusStack *, GProcContext *);
-
 
 
 /* ------------------------- MODULE PYTHON POUR LES SCRIPTS ------------------------- */
@@ -113,61 +134,78 @@ static bool py_plugin_module_define_constants(PyTypeObject *);
 
 
 /* ---------------------------------------------------------------------------------- */
-/*                       INTERFACE INTERNE POUR GREFFONS PYTHON                       */
+/*                          GLUE POUR CREATION DEPUIS 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.                                *
+*  Paramètres  : type = type du nouvel objet à mettre en place.               *
+*                args = éventuelle liste d'arguments.                         *
+*                kwds = éventuel dictionnaire de valeurs mises à disposition. *
 *                                                                             *
-*  Description : Initialise la classe des greffons Python.                    *
+*  Description : Accompagne la création d'une instance dérivée en Python.     *
 *                                                                             *
-*  Retour      : -                                                            *
+*  Retour      : Nouvel objet Python mis en place ou NULL en cas d'échec.     *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-static void g_python_plugin_class_init(GPythonPluginClass *klass)
+static PyObject *py_plugin_module_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
-    GObjectClass *object;                   /* Autre version de la classe  */
+    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   */
 
-    object = G_OBJECT_CLASS(klass);
+    /* Validations diverses */
 
-    object->dispose = (GObjectFinalizeFunc/* ! */)g_python_plugin_dispose;
-    object->finalize = (GObjectFinalizeFunc)g_python_plugin_finalize;
+    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é */
 
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : plugin = instance à initialiser.                             *
-*                                                                             *
-*  Description : Initialise l'instance d'un greffon Python.                   *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
+    first_time = (g_type_from_name(type->tp_name) == 0);
 
-static void g_python_plugin_init(GPythonPlugin *plugin)
-{
+    gtype = built_dynamic_type(G_TYPE_PYTHON_PLUGIN, type->tp_name,
+                               (GClassInitFunc)py_plugin_module_init_gclass, NULL);
+
+    if (first_time)
+        status = register_class_for_dynamic_pygobject(gtype, type, base);
+    else
+        status = true;
+
+    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  : plugin = instance d'objet GLib à traiter.                    *
+*  Paramètres  : class  = classe à initialiser.                               *
+*                unused = données non utilisées ici.                          *
 *                                                                             *
-*  Description : Supprime toutes les références externes.                     *
+*  Description : Initialise la classe des greffons d'extension.               *
 *                                                                             *
 *  Retour      : -                                                            *
 *                                                                             *
@@ -175,191 +213,147 @@ static void g_python_plugin_init(GPythonPlugin *plugin)
 *                                                                             *
 ******************************************************************************/
 
-static void g_python_plugin_dispose(GPythonPlugin *plugin)
+static void py_plugin_module_init_gclass(GPluginModuleClass *class, gpointer unused)
 {
-    PyThreadState *tstate;                  /* Contexte d'environnement    */
+    class->init = NULL;
+    class->exit = NULL;
 
-    /**
-     * 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.
-     */
+    class->native_loaded = py_plugin_module_notify_native_loaded_wrapper;
 
-    tstate = get_pychrysalide_main_tstate();
+    class->include_theme = py_plugin_module_include_theme_wrapper;
 
-    if (tstate != NULL)
-        PyEval_RestoreThread(tstate);
+    class->handle_content = py_plugin_module_handle_binary_content_wrapper;
+    class->handle_loaded = py_plugin_module_handle_loaded_content_wrapper;
 
-    Py_XDECREF(plugin->instance);
-    plugin->instance = NULL;
+    class->handle_fmt_analysis = py_plugin_module_handle_binary_format_analysis_wrapper;
+    class->preload_format = py_plugin_module_preload_binary_format_wrapper;
+    class->attach_debug = py_plugin_module_attach_debug_format_wrapper;
 
-    if (tstate != NULL)
-        PyEval_SaveThread();
+    class->process_disass = py_plugin_module_process_disassembly_event_wrapper;
 
-    G_OBJECT_CLASS(g_python_plugin_parent_class)->dispose(G_OBJECT(plugin));
+    class->detect = py_plugin_module_detect_external_tools_wrapper;
 
 }
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : plugin = instance d'objet GLib à traiter.                    *
+*  Paramètres  : self = objet à initialiser (théoriquement).                  *
+*                args = arguments fournis à l'appel.                          *
+*                kwds = arguments de type key=val fournis.                    *
 *                                                                             *
-*  Description : Procède à la libération totale de la mémoire.                *
+*  Description : Initialise une instance sur la base du dérivé de GObject.    *
 *                                                                             *
-*  Retour      : -                                                            *
+*  Retour      : 0.                                                           *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-static void g_python_plugin_finalize(GPythonPlugin *plugin)
+static int py_plugin_module_init(PyObject *self, PyObject *args, PyObject *kwds)
 {
-    plugin_interface *final;                /* Interface finale conservée  */
+    const char *name;                       /* Désignation humaine courte  */
+    const char *desc;                       /* Description plus loquace    */
+    const char *version;                    /* Version du greffon          */
+    PyObject *actions_obj;                  /* Liste des actions offertes  */
+    int ret;                                /* Bilan de lecture des args.  */
+    PyObject *new_kwds;                     /* Nouveau dictionnaire épuré  */
+    GPluginModule *plugin;                  /* Greffon à manipuler         */
+    plugin_interface *iface;                /* Interface à constituer      */
+    size_t i;                               /* Boucle de parcours          */
+    PyObject *action;                       /* Identifiant d'une action    */
 
-    Py_DECREF(plugin->module);
+    static char *kwlist[] = { "name", "desc", "version", "actions", NULL };
 
-    final = (plugin_interface *)G_PLUGIN_MODULE(plugin)->interface;
+    /* Récupération des paramètres */
 
-    if (final != NULL)
-    {
-        assert(final->required_count == 1);
+    ret = PyArg_ParseTupleAndKeywords(args, kwds, "sssO!", kwlist,
+                                      &name, &desc, &version, &PyTuple_Type, &actions_obj);
+    if (!ret) return -1;
 
-        free(final->required);
-        free(final);
+    /* Initialisation d'un objet GLib */
 
-    }
+    new_kwds = PyDict_New();
 
-    G_OBJECT_CLASS(g_python_plugin_parent_class)->finalize(G_OBJECT(plugin));
+    ret = PyGObject_Type.tp_init(self, args, new_kwds);
 
-}
+    Py_DECREF(new_kwds);
 
+    if (ret == -1) return -1;
 
-/******************************************************************************
-*                                                                             *
-*  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   : -                                                            *
-*                                                                             *
-******************************************************************************/
+    /* Eléments de base */
 
-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 *err_type;                     /* Type d'erreur Python        */
-    PyObject *err_value;                    /* Instance Python d'erreur    */
-    PyObject *err_traceback;                /* Trace Python associée       */
-    PyObject *err_string;                   /* Description Python d'erreur */
-    const char *err_msg;                    /* Représentation humaine      */
-    PyObject *dict;                         /* Dictionnaire associé        */
-    PyObject *class;                        /* Classe à instancier         */
-    PyObject *instance;                     /* Instance Python du greffon  */
-    size_t i;                               /* Boucle de parcours          */
-    uint32_t action;                        /* Identifiant d'une action    */
-    uint32_t category;                      /* Catégorie principale        */
-    uint32_t sub;                           /* Sous-catégorie visée        */
+    plugin = G_PLUGIN_MODULE(pygobject_get(self));
 
-    name = PyUnicode_FromString(modname);
-    if (name == NULL) goto gppn_bad_exit;
+    iface = malloc(sizeof(plugin_interface));
+    plugin->interface = iface;
 
-    module = PyImport_Import(name);
-    Py_DECREF(name);
+    iface->name = strdup(name);
+    iface->desc = strdup(desc);
+    iface->version = strdup(version);
 
-    if (PyErr_Occurred())
-    {
-        PyErr_Fetch(&err_type, &err_value, &err_traceback);
+    iface->container = false;
 
-        if (err_value == NULL)
-            log_variadic_message(LMT_ERROR,
-                                 _("An unknown error occured when importing '%s'..."), modname);
-        else
-        {
-            err_string = PyObject_Str(err_value);
-            err_msg = PyUnicode_AsUTF8(err_string);
+    iface->required = malloc(sizeof(char *));
+    iface->required[0] = "PyChrysalide";
+    iface->required_count = 1;
 
-            log_variadic_message(LMT_ERROR,
-                                 _("An error occured when importing '%s': \"%s\""), modname, err_msg);
+    iface->actions_count = PyTuple_Size(actions_obj);
+    iface->actions = malloc(iface->actions_count * sizeof(plugin_action_t));
 
-            Py_DECREF(err_string);
-            Py_DECREF(err_value);
+    for (i = 0; i < iface->actions_count; i++)
+    {
+        action = PyTuple_GetItem(actions_obj, i);
 
+        if (!PyLong_Check(action))
+        {
+            PyErr_SetString(PyExc_TypeError, _("invalid type for plugin action."));
+            return -1;
         }
 
-        Py_XDECREF(err_traceback);
-        Py_XDECREF(err_type);
-
-        Py_XDECREF(module);
+        iface->actions[i] = PyLong_AsUnsignedLong(action);
 
-        module = NULL;
+    }
 
+    if (!py_plugin_module_check_interface(self))
+    {
+        PyErr_SetString(PyExc_TypeError, _("missing features for the declared actions."));
+        return -1;
     }
 
-    if (module == NULL) goto gppn_bad_exit;
+    return 0;
 
-    dict = PyModule_GetDict(module);
-    class = PyDict_GetItemString(dict, "AutoLoad");
+}
 
-    if (class == NULL) goto gppn_no_class;
-    if (!PyType_Check(class->ob_type)) goto gppn_no_class;
 
-    instance = PyObject_CallFunction(class, NULL);
-    if (instance == NULL) goto gppn_no_instance;
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = greffon Python en cours d'initialisation.             *
+*                                                                             *
+*  Description : Valide les fonctionnalités déclarées en actions.             *
+*                                                                             *
+*  Retour      : true si le greffon Python est à priori utilisable.           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
 
-    result = g_object_new(G_TYPE_PYTHON_PLUGIN, NULL);
+static bool py_plugin_module_check_interface(PyObject *self)
+{
+    bool result;                            /* Bilan à retourner           */
+    GPluginModule *plugin;                  /* Greffon à manipuler         */
+    size_t i;                               /* Boucle de parcours          */
+    uint32_t action;                        /* Identifiant d'une action    */
+    uint32_t category;                      /* Catégorie principale        */
+    uint32_t sub;                           /* Sous-catégorie visée        */
 
-    G_PLUGIN_MODULE(result)->filename = strdup(filename);
+    result = true;
 
-    result->module = module;
-    result->instance = instance;
+    plugin = G_PLUGIN_MODULE(pygobject_get(self));
 
-    if (!g_python_plugin_read_interface(result))
-        goto gppn_interface_error;
-
-    /* Localisation des différents points d'entrée déclarés */
-
-#define register_python_binding(inst, pysym, sym, binding)                          \
-    ({                                                                              \
-        bool __result;                                                              \
-        if (!has_python_method(inst, #pysym))                                       \
-        {                                                                           \
-            log_variadic_message(LMT_ERROR,                                         \
-                                 _("No '%s' entry in plugin candidate '%s'"),       \
-                                 #pysym, G_PLUGIN_MODULE(result)->filename);        \
-            __result = false;                                                       \
-        }                                                                           \
-        else                                                                        \
-        {                                                                           \
-            G_PLUGIN_MODULE(result)->sym = binding;                                 \
-            __result = true;                                                        \
-        }                                                                           \
-        __result;                                                                   \
-    })
-
-    for (i = 0; i < G_PLUGIN_MODULE(result)->interface->actions_count; i++)
+    for (i = 0; i < plugin->interface->actions_count && result; i++)
     {
-        action = G_PLUGIN_MODULE(result)->interface->actions[i];
+        action = plugin->interface->actions[i];
         category = MASK_PLUGIN_CATEGORY(action);
         sub = MASK_PLUGIN_SUB_CATEGORY(action);
 
@@ -373,20 +367,17 @@ GPluginModule *g_python_plugin_new(const char *modname, const char *filename)
                         break;
 
                     case PGA_PLUGIN_INIT:
-                        if (!register_python_binding(instance, init, init,
-                                                     (pg_management_fc)g_python_plugin_do_init))
-                            goto gppn_bad_plugin;
+                        result = has_python_method(self, "init");
                         break;
 
                     case PGA_PLUGIN_EXIT:
-                        if (!register_python_binding(instance, exit, exit,
-                                                     (pg_management_fc)g_python_plugin_do_exit))
-                            goto gppn_bad_plugin;
+                        result = has_python_method(self, "exit");
                         break;
 
                     default:
                         log_variadic_message(LMT_WARNING,
-                                             _("Unknown sub-category '0x%02x' in plugin '%s'..."), sub, filename);
+                                             _("Unknown sub-category '0x%02x' in plugin '%s'..."),
+                                             sub, self->ob_type->tp_name);
                         break;
 
                 }
@@ -402,16 +393,17 @@ GPluginModule *g_python_plugin_new(const char *modname, const char *filename)
                         switch (action)
                         {
                             case PGA_CONTENT_EXPLORER:
+                                result = has_python_method(self, "handle_binary_content");
+                                break;
+
                             case PGA_CONTENT_RESOLVER:
-                                if (!register_python_binding(instance, handle_content, handle_content,
-                                                             (pg_handle_content_fc)g_python_plugin_handle_binary_content))
-                                    goto gppn_bad_plugin;
+                                result = has_python_method(self, "handle_loaded_content");
                                 break;
 
                             default:
                                 log_variadic_message(LMT_WARNING,
                                                      _("Unknown action '0x%02x' in plugin '%s'..."),
-                                                     action, filename);
+                                                     action, self->ob_type->tp_name);
                                 break;
 
                         }
@@ -426,27 +418,21 @@ GPluginModule *g_python_plugin_new(const char *modname, const char *filename)
                             case PGA_FORMAT_ANALYSIS_ENDED:
                             case PGA_FORMAT_POST_ANALYSIS_STARTED:
                             case PGA_FORMAT_POST_ANALYSIS_ENDED:
-                                if (!register_python_binding(instance, handle_format_analysis, handle_fmt_analysis,
-                                                             (pg_handle_format_analysis_fc)g_python_plugin_handle_binary_format_analysis))
-                                    goto gppn_bad_plugin;
+                                result = has_python_method(self, "handle_format_analysis");
                                 break;
 
                             case PGA_FORMAT_PRELOAD:
-                                if (!register_python_binding(instance, preload_format, preload_format,
-                                                             (pg_preload_format_fc)g_python_plugin_preload_binary_format))
-                                    goto gppn_bad_plugin;
+                                result = has_python_method(self, "preload_format");
                                 break;
 
                             case PGA_FORMAT_ATTACH_DEBUG:
-                                if (!register_python_binding(instance, attach_debug_format, attach_debug,
-                                                             (pg_attach_debug)g_python_plugin_attach_debug_format))
-                                    goto gppn_bad_plugin;
+                                result = has_python_method(self, "attach_debug_format");
                                 break;
 
                             default:
                                 log_variadic_message(LMT_WARNING,
                                                      _("Unknown action '0x%02x' in plugin '%s'..."),
-                                                     action, filename);
+                                                     action, self->ob_type->tp_name);
                                 break;
 
                         }
@@ -454,14 +440,13 @@ GPluginModule *g_python_plugin_new(const char *modname, const char *filename)
                         break;
 
                     case DPS_DISASSEMBLY:
-                        if (!register_python_binding(instance, process_disassembly, process_disass,
-                                                     (pg_process_disassembly_fc)g_python_plugin_process_disass))
-                            goto gppn_bad_plugin;
+                        result = has_python_method(self, "process_disassembly");
                         break;
 
                     default:
                         log_variadic_message(LMT_WARNING,
-                                             _("Unknown sub-category '0x%02x' in plugin '%s'..."), sub, filename);
+                                             _("Unknown sub-category '0x%02x' in plugin '%s'..."),
+                                             sub, self->ob_type->tp_name);
                         break;
 
                 }
@@ -470,230 +455,374 @@ GPluginModule *g_python_plugin_new(const char *modname, const char *filename)
 
             default:
                 log_variadic_message(LMT_WARNING,
-                                     _("Unknown category '0x%02x' in plugin '%s'..."), category, filename);
+                                     _("Unknown category '0x%02x' in plugin '%s'..."),
+                                     category, self->ob_type->tp_name);
                 break;
 
         }
 
     }
 
-    /* Conclusion */
+    return result;
 
-    return G_PLUGIN_MODULE(result);
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : plugin = greffon à manipuler.                                *
+*                action = type d'action attendue.                             *
+*                unused = variable non utilisé pour l'usage de __VA_ARGS__.   *
+*                                                                             *
+*  Description : Accompagne la fin du chargement des modules natifs.          *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
 
- gppn_bad_plugin:
+static void py_plugin_module_notify_native_loaded_wrapper(GPluginModule *plugin, PluginAction action)
+{
 
- gppn_interface_error:
+}
 
-    g_object_unref(G_OBJECT(result));
 
-    return NULL;
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : plugin    = greffon à manipuler.                             *
+*                action    = type d'action attendue.                          *
+*                resources = liste de ressources à constituer. [OUT]          *
+*                count     = taille de cette liste. [OUT]                     *
+*                                                                             *
+*  Description : Complète une liste de resources pour thème.                  *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
 
- gppn_no_instance:
+static void py_plugin_module_include_theme_wrapper(const GPluginModule *plugin, PluginAction action, char ***resources, size_t *count)
+{
 
- gppn_no_class:
+}
 
-    Py_DECREF(module);
 
- gppn_bad_exit:
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : plugin  = greffon à manipuler.                               *
+*                action  = type d'action attendue.                            *
+*                content = contenu binaire à traiter.                         *
+*                wid     = identifiant du groupe de traitement.               *
+*                status  = barre de statut à tenir informée.                  *
+*                                                                             *
+*  Description : Procède à une opération liée à un contenu binaire.           *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
 
-    return NULL;
+static void py_plugin_module_handle_binary_content_wrapper(const GPluginModule *plugin, PluginAction action, GBinContent *content, wgroup_id_t wid, GtkStatusStack *status)
+{
+    PyGILState_STATE gstate;                /* Sauvegarde d'environnement  */
+    PyObject *pyobj;                        /* Objet Python concerné       */
+    PyObject *args;                         /* Arguments pour l'appel      */
+    PyObject *value;                        /* Valeurs obtenues            */
+
+    gstate = PyGILState_Ensure();
+
+    pyobj = pygobject_new(G_OBJECT(plugin));
+
+    assert(has_python_method(pyobj, "handle_binary_content"));
+
+    args = PyTuple_New(4);
+
+    PyTuple_SetItem(args, 0, PyLong_FromUnsignedLong(action));
+    PyTuple_SetItem(args, 1, pygobject_new(G_OBJECT(content)));
+    PyTuple_SetItem(args, 2, PyLong_FromUnsignedLong(wid));
+    PyTuple_SetItem(args, 3, pygobject_new(G_OBJECT(status)));
+
+    value = run_python_method(pyobj, "handle_binary_content", args);
+
+    Py_XDECREF(value);
+    Py_DECREF(args);
+
+    PyGILState_Release(gstate);
 
 }
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : plugin = greffon à initialiser.                              *
+*  Paramètres  : plugin  = greffon à manipuler.                               *
+*                action  = type d'action attendue.                            *
+*                content = contenu chargé à traiter.                          *
+*                wid     = identifiant du groupe de traitement.               *
+*                status  = barre de statut à tenir informée.                  *
 *                                                                             *
-*  Description : Reconstruit la déclaration d'interface à partir de lectures. *
+*  Description : Procède à une opération liée à un contenu chargé.            *
 *                                                                             *
-*  Retour      : Bilan de l'opération.                                        *
+*  Retour      : -                                                            *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-static bool g_python_plugin_read_interface(GPythonPlugin *plugin)
+static void py_plugin_module_handle_loaded_content_wrapper(const GPluginModule *plugin, PluginAction action, GLoadedContent *content, wgroup_id_t wid, GtkStatusStack *status)
 {
-    bool result;                            /* Bilan à renvoyer            */
-    plugin_interface interface;             /* Recueil des éléments        */
-    PyObject *desc;                         /* Tableau de description      */
-    PyObject *str;                          /* Chaîne de caractères        */
-    PyObject *tuple;                        /* Liste d'éléments à traiter  */
-    Py_ssize_t count;                       /* Nombre d'éléments présents  */
-    Py_ssize_t i;                           /* Boucle de parcours          */
-    PyObject *action;                       /* Identifiant d'une action    */
-    plugin_interface *final;                /* Interface finale conservée  */
+    PyGILState_STATE gstate;                /* Sauvegarde d'environnement  */
+    PyObject *pyobj;                        /* Objet Python concerné       */
+    PyObject *args;                         /* Arguments pour l'appel      */
+    PyObject *value;                        /* Valeurs obtenues            */
 
-    result = true;
+    gstate = PyGILState_Ensure();
 
-    desc = run_python_method(plugin->instance, "get_interface", NULL);
-    if (!PyDict_Check(desc))
-    {
-        result = false;
-        goto pgpri_end;
-    }
+    pyobj = pygobject_new(G_OBJECT(plugin));
 
-    memset(&interface, 0, sizeof(interface));
+    assert(has_python_method(pyobj, "handle_loaded_content"));
 
-    /* Chargements des premières chaînes */
+    args = PyTuple_New(4);
 
-#define READ_STR_FIELD(name)                            \
-    str = PyDict_GetItemString(desc, #name);            \
-    if ((result = PyUnicode_Check(str)))                \
-        interface.name = strdup(PyUnicode_DATA(str));   \
+    PyTuple_SetItem(args, 0, PyLong_FromUnsignedLong(action));
+    PyTuple_SetItem(args, 1, pygobject_new(G_OBJECT(content)));
+    PyTuple_SetItem(args, 2, PyLong_FromUnsignedLong(wid));
+    PyTuple_SetItem(args, 3, pygobject_new(G_OBJECT(status)));
 
-    READ_STR_FIELD(name);
-    READ_STR_FIELD(desc);
-    READ_STR_FIELD(version);
+    value = run_python_method(pyobj, "handle_loaded_content", args);
 
-    /* Chargement des actions supportées */
+    Py_XDECREF(value);
+    Py_DECREF(args);
 
-    tuple = PyDict_GetItemString(desc, "actions");
+    PyGILState_Release(gstate);
 
-    if (!PyList_Check(tuple))
-    {
-        result = false;
-        goto pgpri_failed;
-    }
+}
 
-    count = PyList_GET_SIZE(tuple);
 
-    interface.actions = (plugin_action_t *)calloc(count, sizeof(plugin_action_t));
-    interface.actions_count = count;
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : plugin = greffon à manipuler.                                *
+*                action = type d'action attendue.                             *
+*                format = format de binaire à manipuler pendant l'opération.  *
+*                gid    = groupe de travail dédié.                            *
+*                status = barre de statut à tenir informée.                   *
+*                                                                             *
+*  Description : Procède à une opération liée à l'analyse d'un format.        *
+*                                                                             *
+*  Retour      : Bilan de l'exécution du traitement.                          *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
 
-    for (i = 0; i < count; i++)
-    {
-        action = PyList_GET_ITEM(tuple, i);
+static bool py_plugin_module_handle_binary_format_analysis_wrapper(const GPluginModule *plugin, PluginAction action, GBinFormat *format, wgroup_id_t gid, GtkStatusStack *status)
+{
+    PyGILState_STATE gstate;                /* Sauvegarde d'environnement  */
+    PyObject *pyobj;                        /* Objet Python concerné       */
+    PyObject *args;                         /* Arguments pour l'appel      */
+    PyObject *value;                        /* Valeurs obtenues            */
 
-        interface.actions[i] = PyLong_AsUnsignedLong(action);
+    gstate = PyGILState_Ensure();
 
-    }
+    pyobj = pygobject_new(G_OBJECT(plugin));
 
- pgpri_failed:
+    assert(has_python_method(pyobj, "handle_format_analysis"));
 
-    if (result)
-    {
-        final = (plugin_interface *)calloc(1, sizeof(plugin_interface));
+    args = PyTuple_New(4);
+
+    PyTuple_SetItem(args, 0, PyLong_FromUnsignedLong(action));
+    PyTuple_SetItem(args, 1, pygobject_new(G_OBJECT(format)));
+    PyTuple_SetItem(args, 2, PyLong_FromUnsignedLong(gid));
+    PyTuple_SetItem(args, 3, pygobject_new(G_OBJECT(status)));
 
-        memcpy(final, &interface, sizeof(interface));
+    value = run_python_method(pyobj, "handle_format_analysis", args);
 
-        final->required = (const char **)malloc(sizeof(char *));
-        final->required[0] = "PyChrysalide";
-        final->required_count = 1;
+    Py_XDECREF(value);
+    Py_DECREF(args);
 
-        G_PLUGIN_MODULE(plugin)->interface = final;
+    PyGILState_Release(gstate);
 
-    }
-    else
-    {
-        if (interface.name != NULL) free((char *)interface.name);
-        if (interface.desc != NULL) free((char *)interface.desc);
-        if (interface.version != NULL) free((char *)interface.version);
+    return true;
 
-        if (interface.actions != NULL) free(interface.actions);
+}
 
-    }
 
- pgpri_end:
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : plugin = greffon à manipuler.                                *
+*                action = type d'action attendue.                             *
+*                format = format de binaire à manipuler pendant l'opération.  *
+*                info   = informations à constituer en avance de phase.       *
+*                status = barre de statut à tenir informée.                   *
+*                                                                             *
+*  Description : Procède à un préchargement de format de fichier.             *
+*                                                                             *
+*  Retour      : Bilan de l'exécution du traitement.                          *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
 
-    Py_XDECREF(desc);
+static bool py_plugin_module_preload_binary_format_wrapper(const GPluginModule *plugin, PluginAction action, GBinFormat *format, GPreloadInfo *info, GtkStatusStack *status)
+{
+    PyGILState_STATE gstate;                /* Sauvegarde d'environnement  */
+    PyObject *pyobj;                        /* Objet Python concerné       */
+    PyObject *args;                         /* Arguments pour l'appel      */
+    PyObject *value;                        /* Valeurs obtenues            */
 
-    return result;
+    gstate = PyGILState_Ensure();
+
+    pyobj = pygobject_new(G_OBJECT(plugin));
+
+    assert(has_python_method(pyobj, "preload_format"));
+
+    args = PyTuple_New(4);
+
+    PyTuple_SetItem(args, 0, PyLong_FromUnsignedLong(action));
+    PyTuple_SetItem(args, 1, pygobject_new(G_OBJECT(format)));
+    PyTuple_SetItem(args, 2, pygobject_new(G_OBJECT(info)));
+    PyTuple_SetItem(args, 3, pygobject_new(G_OBJECT(status)));
+
+    value = run_python_method(pyobj, "preload_format", args);
+
+    Py_XDECREF(value);
+    Py_DECREF(args);
+
+    PyGILState_Release(gstate);
+
+    return true;
 
 }
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : plugin = greffon à initialiser.                              *
-*                ref    = espace de référencement global.                     *
+*  Paramètres  : plugin = greffon à manipuler.                                *
+*                action = type d'action attendue.                             *
+*                format = format de binaire à manipuler pendant l'opération.  *
 *                                                                             *
-*  Description : Procède à l'initialisation du greffon.                       *
+*  Description : Procède au rattachement d'éventuelles infos de débogage.     *
 *                                                                             *
-*  Retour      : Bilan de l'opération.                                        *
+*  Retour      : -                                                            *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-static bool g_python_plugin_do_init(GPythonPlugin *plugin)
+static void py_plugin_module_attach_debug_format_wrapper(const GPluginModule *plugin, PluginAction action, GExeFormat *format)
 {
-    bool result;                            /* Bilan à retourner           */
-    PyThreadState *tstate;                  /* Contexte d'environnement    */
-    PyObject *value;                        /* Valeur obtenue              */
+    PyGILState_STATE gstate;                /* Sauvegarde d'environnement  */
+    PyObject *pyobj;                        /* Objet Python concerné       */
+    PyObject *args;                         /* Arguments pour l'appel      */
+    PyObject *value;                        /* Valeurs obtenues            */
+
+    gstate = PyGILState_Ensure();
 
-    tstate = PyThreadState_Get();
+    pyobj = pygobject_new(G_OBJECT(plugin));
 
-    if (tstate != NULL)
-        PyEval_RestoreThread(tstate);
+    assert(has_python_method(pyobj, "attach_debug_format"));
 
-    if (!has_python_method(plugin->instance, "init"))
-        result = true;
+    args = PyTuple_New(2);
 
-    else
-    {
-        value = run_python_method(plugin->instance, "init", NULL);
+    PyTuple_SetItem(args, 0, PyLong_FromUnsignedLong(action));
+    PyTuple_SetItem(args, 1, pygobject_new(G_OBJECT(format)));
 
-        result = (value != NULL && PyObject_IsTrue(value));
+    value = run_python_method(pyobj, "attach_debug_format", args);
 
-        Py_XDECREF(value);
+    Py_XDECREF(value);
+    Py_DECREF(args);
 
-    }
+    PyGILState_Release(gstate);
 
-    if (tstate != NULL)
-        PyEval_SaveThread();
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : plugin = greffon à manipuler.                                *
+*                action = type d'action attendue.                             *
+*                binary = binaire dont le contenu est en cours de traitement. *
+*                status  = barre de statut à tenir informée.                  *
+*                context = contexte de désassemblage.                         *
+*                                                                             *
+*  Description : Exécute une action pendant un désassemblage de binaire.      *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void py_plugin_module_process_disassembly_event_wrapper(const GPluginModule *plugin, PluginAction action, GLoadedBinary *binary, GtkStatusStack *status, GProcContext *context)
+{
+    PyGILState_STATE gstate;                /* Sauvegarde d'environnement  */
+    PyObject *pyobj;                        /* Objet Python concerné       */
+    PyObject *args;                         /* Arguments pour l'appel      */
+    PyObject *value;                        /* Valeurs obtenues            */
+
+    gstate = PyGILState_Ensure();
+
+    pyobj = pygobject_new(G_OBJECT(plugin));
+
+    assert(has_python_method(pyobj, "process_disassembly"));
+
+    args = PyTuple_New(4);
+
+    PyTuple_SetItem(args, 0, PyLong_FromUnsignedLong(action));
+    PyTuple_SetItem(args, 1, pygobject_new(G_OBJECT(binary)));
+    PyTuple_SetItem(args, 2, pygobject_new(G_OBJECT(status)));
+    PyTuple_SetItem(args, 3, pygobject_new(G_OBJECT(context)));
+
+    value = run_python_method(pyobj, "process_disassembly", args);
 
-    return result;
+    Py_XDECREF(value);
+    Py_DECREF(args);
+
+    PyGILState_Release(gstate);
 
 }
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : plugin = greffon à initialiser.                              *
+*  Paramètres  : plugin  = greffon à manipuler.                               *
+*                action  = type d'action attendue.                            *
+*                content = élément chargé à consulter.                        *
+*                version = précise si les versions doivent être recherchées.  *
+*                names   = désignations humaines correspondantes, à libérer.  *
+*                count   = nombre de types d'obscurcissement trouvés. [OUT]   *
 *                                                                             *
-*  Description : Procède à l'extinction du greffon.                           *
+*  Description : Effectue la détection d'effets d'outils externes.            *
 *                                                                             *
-*  Retour      : Bilan de l'opération.                                        *
+*  Retour      : -                                                            *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-static bool g_python_plugin_do_exit(GPythonPlugin *plugin)
+static void py_plugin_module_detect_external_tools_wrapper(const GPluginModule *plugin, PluginAction action, const GLoadedContent *content, bool version, char ***names, size_t *count)
 {
-    bool result;                            /* Bilan à retourner           */
-    PyObject *value;                        /* Valeur obtenue              */
 
-    if (!has_python_method(plugin->instance, "exit"))
-        result = true;
-
-    else
-    {
-        value = run_python_method(plugin->instance, "exit", NULL);
+}
 
-        result = (value != NULL && PyObject_IsTrue(value));
 
-        Py_XDECREF(value);
 
-    }
+/* ---------------------------------------------------------------------------------- */
+/*                       INTERFACE INTERNE POUR GREFFONS PYTHON                       */
+/* ---------------------------------------------------------------------------------- */
 
-    return result;
 
-}
+/* 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  : plugin  = greffon à manipuler.                               *
-*                action  = type d'action attendue.                            *
-*                content = contenu binaire à traiter.                         *
-*                wid     = identifiant du groupe de traitement.               *
-*                status  = barre de statut à tenir informée.                  *
+*  Paramètres  : klass = classe à initialiser.                                *
 *                                                                             *
-*  Description : Procède à une opération liée à un contenu binaire.           *
+*  Description : Initialise la classe des greffons Python.                    *
 *                                                                             *
 *  Retour      : -                                                            *
 *                                                                             *
@@ -701,124 +830,94 @@ static bool g_python_plugin_do_exit(GPythonPlugin *plugin)
 *                                                                             *
 ******************************************************************************/
 
-static void g_python_plugin_handle_binary_content(const GPythonPlugin *plugin, PluginAction action, GBinContent *content, wgroup_id_t wid, GtkStatusStack *status)
+static void g_python_plugin_class_init(GPythonPluginClass *klass)
 {
-    PyGILState_STATE gstate;                /* Sauvegarde d'environnement  */
-    PyObject *args;                         /* Arguments pour l'appel      */
-    PyObject *value;                        /* Valeurs obtenues            */
-
-    gstate = PyGILState_Ensure();
-
-    args = PyTuple_New(4);
-
-    PyTuple_SetItem(args, 0, PyLong_FromUnsignedLong(action));
-    PyTuple_SetItem(args, 1, pygobject_new(G_OBJECT(content)));
-    PyTuple_SetItem(args, 2, PyLong_FromUnsignedLong(wid));
-    PyTuple_SetItem(args, 3, pygobject_new(G_OBJECT(status)));
-
-    value = run_python_method(plugin->instance, "handle_content", args);
+    GObjectClass *object;                   /* Autre version de la classe  */
 
-    Py_XDECREF(value);
-    Py_DECREF(args);
+    object = G_OBJECT_CLASS(klass);
 
-    PyGILState_Release(gstate);
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_python_plugin_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_python_plugin_finalize;
 
 }
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : plugin = greffon à manipuler.                                *
-*                action = type d'action attendue.                             *
-*                format = format de binaire à manipuler pendant l'opération.  *
-*                gid    = groupe de travail dédié.                            *
-*                status = barre de statut à tenir informée.                   *
+*  Paramètres  : plugin = instance à initialiser.                             *
 *                                                                             *
-*  Description : Procède à une opération liée à l'analyse d'un format.        *
+*  Description : Initialise l'instance d'un greffon Python.                   *
 *                                                                             *
-*  Retour      : Bilan de l'exécution du traitement.                          *
+*  Retour      : -                                                            *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-static bool g_python_plugin_handle_binary_format_analysis(const GPythonPlugin *plugin, PluginAction action, GBinFormat *format, wgroup_id_t gid, GtkStatusStack *status)
+static void g_python_plugin_init(GPythonPlugin *plugin)
 {
-    PyGILState_STATE gstate;                /* Sauvegarde d'environnement  */
-    PyObject *args;                         /* Arguments pour l'appel      */
-    PyObject *value;                        /* Valeurs obtenues            */
-
-    gstate = PyGILState_Ensure();
-
-    args = PyTuple_New(4);
-
-    PyTuple_SetItem(args, 0, PyLong_FromUnsignedLong(action));
-    PyTuple_SetItem(args, 1, pygobject_new(G_OBJECT(format)));
-    PyTuple_SetItem(args, 2, PyLong_FromUnsignedLong(gid));
-    PyTuple_SetItem(args, 3, pygobject_new(G_OBJECT(status)));
-
-    value = run_python_method(plugin->instance, "handle_format_analysis", args);
-
-    Py_XDECREF(value);
-    Py_DECREF(args);
-
-    PyGILState_Release(gstate);
-
-    return true;
 
 }
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : plugin = greffon à manipuler.                                *
-*                action = type d'action attendue.                             *
-*                format = format de binaire à manipuler pendant l'opération.  *
-*                info   = informations à constituer en avance de phase.       *
-*                status = barre de statut à tenir informée.                   *
+*  Paramètres  : plugin = instance d'objet GLib à traiter.                    *
 *                                                                             *
-*  Description : Procède à un préchargement de format de fichier.             *
+*  Description : Supprime toutes les références externes.                     *
 *                                                                             *
-*  Retour      : Bilan de l'exécution du traitement.                          *
+*  Retour      : -                                                            *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-static bool g_python_plugin_preload_binary_format(const GPythonPlugin *plugin, PluginAction action, GBinFormat *format, GPreloadInfo *info, GtkStatusStack *status)
+static void g_python_plugin_dispose(GPythonPlugin *plugin)
 {
-    PyGILState_STATE gstate;                /* Sauvegarde d'environnement  */
-    PyObject *args;                         /* Arguments pour l'appel      */
-    PyObject *value;                        /* Valeurs obtenues            */
-
-    gstate = PyGILState_Ensure();
+    PyThreadState *tstate;                  /* Contexte d'environnement    */
 
-    args = PyTuple_New(4);
+    /**
+     * 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.
+     */
 
-    PyTuple_SetItem(args, 0, PyLong_FromUnsignedLong(action));
-    PyTuple_SetItem(args, 1, pygobject_new(G_OBJECT(format)));
-    PyTuple_SetItem(args, 2, pygobject_new(G_OBJECT(info)));
-    PyTuple_SetItem(args, 3, pygobject_new(G_OBJECT(status)));
+    tstate = get_pychrysalide_main_tstate();
 
-    value = run_python_method(plugin->instance, "preload_format", args);
+    if (tstate != NULL)
+        PyEval_RestoreThread(tstate);
 
-    Py_XDECREF(value);
-    Py_DECREF(args);
+    Py_XDECREF(plugin->instance);
+    plugin->instance = NULL;
 
-    PyGILState_Release(gstate);
+    if (tstate != NULL)
+        PyEval_SaveThread();
 
-    return true;
+    G_OBJECT_CLASS(g_python_plugin_parent_class)->dispose(G_OBJECT(plugin));
 
 }
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : plugin = greffon à manipuler.                                *
-*                action = type d'action attendue.                             *
-*                format = format de binaire à manipuler pendant l'opération.  *
+*  Paramètres  : plugin = instance d'objet GLib à traiter.                    *
 *                                                                             *
-*  Description : Procède au rattachement d'éventuelles infos de débogage.     *
+*  Description : Procède à la libération totale de la mémoire.                *
 *                                                                             *
 *  Retour      : -                                                            *
 *                                                                             *
@@ -826,66 +925,121 @@ static bool g_python_plugin_preload_binary_format(const GPythonPlugin *plugin, P
 *                                                                             *
 ******************************************************************************/
 
-static void g_python_plugin_attach_debug_format(const GPythonPlugin *plugin, PluginAction action, GExeFormat *format)
+static void g_python_plugin_finalize(GPythonPlugin *plugin)
 {
-    PyGILState_STATE gstate;                /* Sauvegarde d'environnement  */
-    PyObject *args;                         /* Arguments pour l'appel      */
-    PyObject *value;                        /* Valeurs obtenues            */
+    plugin_interface *final;                /* Interface finale conservée  */
 
-    gstate = PyGILState_Ensure();
+    Py_XDECREF(plugin->module);
 
-    args = PyTuple_New(2);
+    final = (plugin_interface *)G_PLUGIN_MODULE(plugin)->interface;
 
-    PyTuple_SetItem(args, 0, PyLong_FromUnsignedLong(action));
-    PyTuple_SetItem(args, 1, pygobject_new(G_OBJECT(format)));
+    if (final != NULL)
+    {
+        assert(final->required_count == 1);
+        free(final->required);
 
-    value = run_python_method(plugin->instance, "attach_debug_format", args);
+        free(final);
 
-    Py_XDECREF(value);
-    Py_DECREF(args);
+    }
 
-    PyGILState_Release(gstate);
+    G_OBJECT_CLASS(g_python_plugin_parent_class)->finalize(G_OBJECT(plugin));
 
 }
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : plugin  = greffon à manipuler.                               *
-*                action  = type d'action attendue.                            *
-*                binary  = binaire dont le contenu est en cours de traitement.*
-*                status  = barre de statut à tenir informée.                  *
-*                context = contexte de désassemblage.                         *
+*  Paramètres  : modname  = nom du module à charger.                          *
+*                filename = chemin d'accès au code Python à charger.          *
 *                                                                             *
-*  Description : Exécute une action pendant un désassemblage de binaire.      *
+*  Description : Crée un greffon à partir de code Python.                     *
 *                                                                             *
-*  Retour      : -                                                            *
+*  Retour      : Adresse de la structure mise en place ou NULL si erreur.     *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-static void g_python_plugin_process_disass(const GPythonPlugin *plugin, PluginAction action, GLoadedBinary *binary, GtkStatusStack *status, GProcContext *context)
+GPluginModule *g_python_plugin_new(const char *modname, const char *filename)
 {
-    PyGILState_STATE gstate;                /* Sauvegarde d'environnement  */
-    PyObject *args;                         /* Arguments pour l'appel      */
-    PyObject *value;                        /* Valeurs obtenues            */
+    GPythonPlugin *result;                  /* Structure à retourner       */
+    PyObject *name;                         /* Chemin d'accès pour Python  */
+    PyObject *module;                       /* Script Python chargé        */
+    PyObject *err_type;                     /* Type d'erreur Python        */
+    PyObject *err_value;                    /* Instance Python d'erreur    */
+    PyObject *err_traceback;                /* Trace Python associée       */
+    PyObject *err_string;                   /* Description Python d'erreur */
+    const char *err_msg;                    /* Représentation humaine      */
+    PyObject *dict;                         /* Dictionnaire associé        */
+    PyObject *class;                        /* Classe à instancier         */
+    PyObject *instance;                     /* Instance Python du greffon  */
 
-    gstate = PyGILState_Ensure();
+    name = PyUnicode_FromString(modname);
+    if (name == NULL) goto gppn_bad_exit;
 
-    args = PyTuple_New(4);
+    module = PyImport_Import(name);
+    Py_DECREF(name);
 
-    PyTuple_SetItem(args, 0, PyLong_FromUnsignedLong(action));
-    PyTuple_SetItem(args, 1, pygobject_new(G_OBJECT(binary)));
-    PyTuple_SetItem(args, 2, pygobject_new(G_OBJECT(status)));
-    PyTuple_SetItem(args, 3, pygobject_new(G_OBJECT(context)));
+    if (PyErr_Occurred())
+    {
+        PyErr_Fetch(&err_type, &err_value, &err_traceback);
 
-    value = run_python_method(plugin->instance, "process_disassembly", args);
+        if (err_value == NULL)
+            log_variadic_message(LMT_ERROR,
+                                 _("An unknown error occured when importing '%s'..."), modname);
+        else
+        {
+            err_string = PyObject_Str(err_value);
+            err_msg = PyUnicode_AsUTF8(err_string);
 
-    Py_XDECREF(value);
-    Py_DECREF(args);
+            log_variadic_message(LMT_ERROR,
+                                 _("An error occured when importing '%s': \"%s\""), modname, err_msg);
 
-    PyGILState_Release(gstate);
+            Py_DECREF(err_string);
+            Py_DECREF(err_value);
+
+        }
+
+        Py_XDECREF(err_traceback);
+        Py_XDECREF(err_type);
+
+        Py_XDECREF(module);
+
+        module = NULL;
+
+    }
+
+    if (module == NULL) goto gppn_bad_exit;
+
+    dict = PyModule_GetDict(module);
+    class = PyDict_GetItemString(dict, "AutoLoad");
+
+    if (class == NULL) goto gppn_no_class;
+    if (!PyType_Check(class->ob_type)) goto gppn_no_class;
+
+    instance = PyObject_CallFunction(class, NULL);
+    if (instance == NULL) goto gppn_no_instance;
+
+    result = G_PYTHON_PLUGIN(pygobject_get(instance));
+
+    G_PLUGIN_MODULE(result)->filename = strdup(filename);
+
+    result->module = module;
+    result->instance = instance;
+
+    Py_INCREF(instance);
+
+    return G_PLUGIN_MODULE(result);
+
+ gppn_no_instance:
+
+ gppn_no_class:
+
+    Py_DECREF(module);
+
+ gppn_bad_exit:
+
+    return NULL;
 
 }
 
@@ -926,7 +1080,7 @@ static PyObject *py_plugin_module_log_message(PyObject *self, PyObject *args)
         case LMT_BAD_BINARY:
         case LMT_ERROR:
         case LMT_EXT_ERROR:
-            /*g_plugin_module_*/log_simple_message(/*G_PLUGIN_MODULE(pygobject_get(self)), */type, msg);
+            g_plugin_module_log_simple_message(G_PLUGIN_MODULE(pygobject_get(self)), type, msg);
             result = Py_None;
             Py_INCREF(result);
             break;
@@ -1037,7 +1191,10 @@ PyTypeObject *get_python_plugin_module_type(void)
         .tp_doc         = "Chrysalide plugin for Python.",
 
         .tp_methods     = py_plugin_module_methods,
-        .tp_getset      = py_plugin_module_getseters
+        .tp_getset      = py_plugin_module_getseters,
+
+        .tp_init        = py_plugin_module_init,
+        .tp_new         = py_plugin_module_new,
 
     };
 
@@ -1072,7 +1229,7 @@ bool ensure_python_plugin_module_is_registered(void)
 
         dict = PyModule_GetDict(module);
 
-        if (!register_class_for_pygobject(dict, G_TYPE_PLUGIN_MODULE, type, &PyGObject_Type))
+        if (!register_class_for_pygobject(dict, G_TYPE_PYTHON_PLUGIN, type, &PyGObject_Type))
             return false;
 
         if (!py_plugin_module_define_constants(type))
diff --git a/plugins/pychrysalide/pychrysa.c b/plugins/pychrysalide/pychrysa.c
index 8849981..502bf20 100644
--- a/plugins/pychrysalide/pychrysa.c
+++ b/plugins/pychrysalide/pychrysa.c
@@ -45,7 +45,6 @@
 
 #include "access.h"
 #include "constval.h"
-#include "dt.h"
 #include "helpers.h"
 #include "plugin.h"
 #include "star.h"
@@ -63,7 +62,7 @@
 
 
 
-DEFINE_CHRYSALIDE_CONTAINER_PLUGIN("PyChrysalide", "Provides bindings to Python", "0.1.0",
+DEFINE_CHRYSALIDE_CONTAINER_PLUGIN("GPyChrysalidePlugin", "PyChrysalide", "Provides bindings to Python", "0.1.0",
                                    EMPTY_PG_LIST(.required), AL(PGA_PLUGIN_INIT, PGA_PLUGIN_EXIT, PGA_NATIVE_LOADED));
 
 
@@ -368,8 +367,6 @@ PyMODINIT_FUNC PyInit_pychrysalide(void)
 
     /* Mise en place des fonctionnalités offertes */
 
-    init_dynamic_python_types();
-
     result = PyModule_Create(&py_chrysalide_module);
 
     register_access_to_python_module(py_chrysalide_module.m_name, result);
diff --git a/plugins/readdex/reader.c b/plugins/readdex/reader.c
index 5b84a0d..2009ad6 100644
--- a/plugins/readdex/reader.c
+++ b/plugins/readdex/reader.c
@@ -34,7 +34,7 @@
 
 
 
-DEFINE_CHRYSALIDE_ACTIVE_PLUGIN("readdex", "Displays information about DEX files", "0.2.0",
+DEFINE_CHRYSALIDE_ACTIVE_PLUGIN("GDexReaderPlugin", "readdex", "Displays information about DEX files", "0.2.0",
                                 PGA_FORMAT_PRELOAD);
 
 
diff --git a/plugins/readelf/reader.c b/plugins/readelf/reader.c
index b137659..ba4d17a 100644
--- a/plugins/readelf/reader.c
+++ b/plugins/readelf/reader.c
@@ -35,7 +35,7 @@
 
 
 
-DEFINE_CHRYSALIDE_ACTIVE_PLUGIN("readelf", "Displays information about ELF files", "0.2.0",
+DEFINE_CHRYSALIDE_ACTIVE_PLUGIN("GElfReaderPlugin", "readelf", "Displays information about ELF files", "0.2.0",
                                 PGA_FORMAT_PRELOAD);
 
 
diff --git a/plugins/readmc/reader.c b/plugins/readmc/reader.c
index e10b927..e492eeb 100644
--- a/plugins/readmc/reader.c
+++ b/plugins/readmc/reader.c
@@ -36,7 +36,7 @@
 
 
 
-DEFINE_CHRYSALIDE_ACTIVE_PLUGIN("readmc", "Displays information about Mobicore files", "0.2.0",
+DEFINE_CHRYSALIDE_ACTIVE_PLUGIN("GMCReaderPlugin", "readmc", "Displays information about Mobicore files", "0.2.0",
                                 PGA_FORMAT_PRELOAD);
 
 
diff --git a/plugins/ropgadgets/plugin.c b/plugins/ropgadgets/plugin.c
index 1ecb7d8..d560c88 100644
--- a/plugins/ropgadgets/plugin.c
+++ b/plugins/ropgadgets/plugin.c
@@ -36,7 +36,7 @@
 
 
 
-DEFINE_CHRYSALIDE_PLUGIN("ROP gadgets", "Find available gadgets for a ROP chain", "0.1.0",
+DEFINE_CHRYSALIDE_PLUGIN("GROPPlugin", "ROP gadgets", "Find available gadgets for a ROP chain", "0.1.0",
                          RL("PyChrysalide"), AL(PGA_PLUGIN_INIT));
 
 
diff --git a/src/core/core.c b/src/core/core.c
index cdcfce5..aabff62 100644
--- a/src/core/core.c
+++ b/src/core/core.c
@@ -44,6 +44,7 @@
 #include "../common/io.h"
 #include "../common/xdg.h"
 #include "../glibext/linesegment.h"
+#include "../plugins/dt.h"
 
 
 
@@ -87,6 +88,8 @@ bool load_all_basic_components(void)
         SSL_load_error_strings();
         SSL_library_init();
 
+        result &= init_chrysalide_dynamic_types();
+
         result &= load_main_config_parameters();
 
         result &= ensure_user_has_rsa_keys();
@@ -142,6 +145,8 @@ void unload_all_basic_components(void)
 
     unload_main_config_parameters();
 
+    exit_chrysalide_dynamic_types();
+
     ERR_free_strings();
 
 }
diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am
index 996c418..4059e0b 100644
--- a/src/plugins/Makefile.am
+++ b/src/plugins/Makefile.am
@@ -4,6 +4,7 @@ noinst_LTLIBRARIES = libplugins.la
 libplugins_la_SOURCES =					\
 	context-int.h						\
 	context.h context.c					\
+	dt.h dt.c							\
 	pglist.h pglist.c					\
 	plugin-def.h						\
 	plugin-int.h						\
diff --git a/src/plugins/dt.c b/src/plugins/dt.c
new file mode 100644
index 0000000..afdba21
--- /dev/null
+++ b/src/plugins/dt.c
@@ -0,0 +1,474 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * dt.c - possibilité de créer de nouveaux types de façon dynamique
+ *
+ * Copyright (C) 2018 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  Chrysalide is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Chrysalide.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "dt.h"
+
+
+#include <assert.h>
+#include <malloc.h>
+
+
+
+/* ------------------------- MODULE DE GESTION DES NOUVEAUX ------------------------- */
+
+
+#define G_TYPE_DYNAMIC_TYPES            g_dynamic_types_get_type()
+#define G_DYNAMIC_TYPES(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_DYNAMIC_TYPES, GDynamicTypes))
+#define G_IS_DYNAMIC_TYPES(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_DYNAMIC_TYPES))
+#define G_DYNAMIC_TYPES_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_DYNAMIC_TYPES, GDynamicTypesClass))
+#define G_IS_DYNAMIC_TYPES_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_DYNAMIC_TYPES))
+#define G_DYNAMIC_TYPES_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DYNAMIC_TYPES, GDynamicTypesClass))
+
+
+/* Mémorisation des caractéristiques de type */
+typedef struct _type_dyn_info_t
+{
+    GType type;                             /* Identifiant unique obtenu   */
+    GClassInitFunc init;                    /* Définition des méthodes     */
+    gconstpointer data;                     /* Eventuelles données utiles  */
+
+} type_dyn_info_t;
+
+/* Description de fichier binaire (instance) */
+typedef struct _GDynamicTypes
+{
+    GObject parent;                         /* A laisser en premier        */
+
+    type_dyn_info_t **info;                 /* Liste d'informations utiles */
+    size_t count;                           /* Taille de cette liste       */
+
+} GDynamicTypes;
+
+/* Description de fichier binaire (classe) */
+typedef struct _GDynamicTypesClass
+{
+    GObjectClass parent;                    /* A laisser en premier        */
+
+} GDynamicTypesClass;
+
+
+/* Indique le type défini pour une gestion de types dynamique. */
+static GType g_dynamic_types_get_type(void);
+
+/* Initialise la classe de gestion de types dynamique. */
+static void g_dynamic_types_class_init(GDynamicTypesClass *);
+
+/* Initialise une gestion de types dynamique. */
+static void g_dynamic_types_init(GDynamicTypes *);
+
+/* Procède à l'initialisation de l'interface de typage nouveau. */
+static void g_dynamic_types_interface_init(GTypePluginClass *);
+
+/* Supprime toutes les références externes. */
+static void g_dynamic_types_dispose(GDynamicTypes *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_dynamic_types_finalize(GDynamicTypes *);
+
+/* Crée un nouveau gestionnaire de nouveaux types. */
+static GDynamicTypes *g_dynamic_types_new(void);
+
+/* Marque une augmentation des utilisations. */
+static void g_dynamic_types_use(GDynamicTypes *);
+
+/* Marque une diminution des utilisations. */
+static void g_dynamic_types_unuse(GDynamicTypes *);
+
+/* Complète la définition d'un type dynamiquement. */
+static void g_dynamic_types_complete_type(GDynamicTypes *, GType, GTypeInfo *, GTypeValueTable *);
+
+/* Retrouve les informations concernant un type dynamique. */
+static const type_dyn_info_t *g_dynamic_types_find(const GDynamicTypes *, GType);
+
+/* Fournit un identifiant GLib pour un nouveau type. */
+static GType g_dynamic_types_register_type(GDynamicTypes *, GType, const char *, GClassInitFunc, gconstpointer);
+
+
+
+/* ----------------------- ACCOMPAGNEMENTS DES NOUVEAUX TYPES ----------------------- */
+
+
+/* Encadrement des nouveaux types dérivés */
+static GDynamicTypes *_chrysalide_dtypes = NULL;
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                           MODULE DE GESTION DES NOUVEAUX                           */
+/* ---------------------------------------------------------------------------------- */
+
+/* Indique le type défini pour une gestion de types dynamique. */
+G_DEFINE_TYPE_WITH_CODE(GDynamicTypes, g_dynamic_types, G_TYPE_OBJECT,
+                        G_IMPLEMENT_INTERFACE(G_TYPE_TYPE_PLUGIN, g_dynamic_types_interface_init));
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : klass = classe à initialiser.                                *
+*                                                                             *
+*  Description : Initialise la classe de gestion de types dynamique.          *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_dynamic_types_class_init(GDynamicTypesClass *klass)
+{
+    GObjectClass *object;                   /* Autre version de la classe  */
+
+    object = G_OBJECT_CLASS(klass);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_dynamic_types_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_dynamic_types_finalize;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : types = instance à initialiser.                              *
+*                                                                             *
+*  Description : Initialise une gestion de types dynamique.                   *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_dynamic_types_init(GDynamicTypes *types)
+{
+
+}
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : iface = interface GLib à initialiser.                        *
+*                                                                             *
+*  Description : Procède à l'initialisation de l'interface de typage nouveau. *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_dynamic_types_interface_init(GTypePluginClass *iface)
+{
+    iface->use_plugin = (GTypePluginUse)g_dynamic_types_use;
+    iface->unuse_plugin = (GTypePluginUnuse)g_dynamic_types_unuse;
+    iface->complete_type_info = (GTypePluginCompleteTypeInfo)g_dynamic_types_complete_type;
+
+}
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : types = instance d'objet GLib à traiter.                     *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_dynamic_types_dispose(GDynamicTypes *types)
+{
+    G_OBJECT_CLASS(g_dynamic_types_parent_class)->dispose(G_OBJECT(types));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : types = instance d'objet GLib à traiter.                     *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_dynamic_types_finalize(GDynamicTypes *types)
+{
+    G_OBJECT_CLASS(g_dynamic_types_parent_class)->finalize(G_OBJECT(types));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Crée un nouveau gestionnaire de nouveaux types.              *
+*                                                                             *
+*  Retour      : Instance mise en place.                                      *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static GDynamicTypes *g_dynamic_types_new(void)
+{
+    GDynamicTypes *result;                  /* Adresse à retourner         */
+
+    result = g_object_new(G_TYPE_DYNAMIC_TYPES, NULL);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : types = gestionnaire de types courant.                       *
+*                                                                             *
+*  Description : Marque une augmentation des utilisations.                    *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_dynamic_types_use(GDynamicTypes *types)
+{
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : types = gestionnaire de types courant.                       *
+*                                                                             *
+*  Description : Marque une diminution des utilisations.                      *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_dynamic_types_unuse(GDynamicTypes *types)
+{
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : types = gestionnaire de types courant.                       *
+*                type  = nouveau type GLib à traiter.                         *
+*                info  = information concernant ce type à constituer. [OUT]   *
+*                table = table de valeur à éventuellement initialiser. [OUT]  *
+*                                                                             *
+*  Description : Complète la définition d'un type dynamiquement.              *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_dynamic_types_complete_type(GDynamicTypes *types, GType type, GTypeInfo *info, GTypeValueTable *table)
+{
+    const type_dyn_info_t *nfo;             /* Source d'inspiration        */
+    GType parent;                           /* Type parent du type         */
+    GTypeQuery query;                       /* Informations complémentaires*/
+
+    /* Consultation */
+
+    nfo = g_dynamic_types_find(types, type);
+    assert(nfo != NULL);
+
+    parent = g_type_parent(type);
+    g_type_query(parent, &query);
+
+    /* Définition */
+
+    info->class_size = query.class_size;
+    info->class_init = nfo->init;
+    info->class_data = nfo->data;
+
+    info->instance_size = query.instance_size;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : parent = type GLib parent.                                   *
+*                type   = identifiant du type GLib à considérer.              *
+*                                                                             *
+*  Description : Retrouve les informations concernant un type dynamique.      *
+*                                                                             *
+*  Retour      : Structure contenant les informations associées au type.      *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static const type_dyn_info_t *g_dynamic_types_find(const GDynamicTypes *types, GType target)
+{
+    type_dyn_info_t *result;                /* Informations à retourner    */
+    size_t i;                               /* Boucle de parcours          */
+
+    result = NULL;
+
+    for (i = 0; i < types->count && result == NULL; i++)
+        if (types->info[i]->type == target)
+            result = types->info[i];
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : parent = type GLib parent.                                   *
+*                name   = désignation du nouveau type.                        *
+*                init   = procédure d'initialisation de la classe associée.   *
+*                data   = éventuelles données à associer à la future classe.  *
+*                                                                             *
+*  Description : Fournit un identifiant GLib pour un nouveau type.            *
+*                                                                             *
+*  Retour      : identifiant d'un nouveau type valide, ou 0.                  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static GType g_dynamic_types_register_type(GDynamicTypes *types, GType parent, const char *name, GClassInitFunc init, gconstpointer data)
+{
+    GType result;                           /* Identifiant à retourner     */
+    type_dyn_info_t *new;                   /* Mémorisation de paramètres  */
+
+    /* Création d'un nouveau type adapté */
+
+    result = g_type_register_dynamic(parent, name, G_TYPE_PLUGIN(types), 0);
+
+    if (result == 0)
+        goto exit;
+
+    new = malloc(sizeof(type_dyn_info_t));
+
+    new->type = result;
+    new->init = init;
+    new->data = data;
+
+    /* Inscription définitive */
+
+    types->info = realloc(types->info, ++types->count * sizeof(type_dyn_info_t *));
+
+    types->info[types->count - 1] = new;
+
+ exit:
+
+    return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                         ACCOMPAGNEMENTS DES NOUVEAUX TYPES                         */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Lance le support de dérivations de types dans Chrysalide.    *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool init_chrysalide_dynamic_types(void)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    _chrysalide_dtypes = g_dynamic_types_new();
+
+    result = (_chrysalide_dtypes != NULL);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Arrête le support de dérivations de types dans Chrysalide.   *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void exit_chrysalide_dynamic_types(void)
+{
+    g_object_unref(G_OBJECT(_chrysalide_dtypes));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : parent = type GLib parent.                                   *
+*                name   = désignation du nouveau type.                        *
+*                init   = procédure d'initialisation de la classe associée.   *
+*                data   = éventuelles données à associer à la future classe.  *
+*                                                                             *
+*  Description : Fournit un identifiant GLib pour un nouveau type.            *
+*                                                                             *
+*  Retour      : Identifiant d'un nouveau type valide, ou 0.                  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GType built_dynamic_type(GType parent, const char *name, GClassInitFunc init, gconstpointer data)
+{
+    GType result;                           /* Identifiant à retourner     */
+
+    result = g_type_from_name(name);
+
+    if (result == 0)
+        result = g_dynamic_types_register_type(_chrysalide_dtypes, parent, name, init, data);
+
+    return result;
+
+}
diff --git a/src/plugins/dt.h b/src/plugins/dt.h
new file mode 100644
index 0000000..b9d4656
--- /dev/null
+++ b/src/plugins/dt.h
@@ -0,0 +1,47 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * dt.h - prototypes pour la possibilité de créer de nouveaux types de façon dynamique
+ *
+ * Copyright (C) 2018 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  Chrysalide is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Chrysalide.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_DT_H
+#define _PLUGINS_DT_H
+
+
+#include <glib-object.h>
+#include <stdbool.h>
+
+
+
+/* ----------------------- ACCOMPAGNEMENTS DES NOUVEAUX TYPES ----------------------- */
+
+
+/* Lance le support de dérivations de types dans Chrysalide. */
+bool init_chrysalide_dynamic_types(void);
+
+/* Arrête le support de dérivations de types dans Chrysalide. */
+void exit_chrysalide_dynamic_types(void);
+
+/* Fournit un identifiant GLib pour un nouveau type. */
+GType built_dynamic_type(GType, const char *, GClassInitFunc, gconstpointer);
+
+
+
+#endif  /* _PLUGINS_PYCHRYSALIDE_DT_H */
diff --git a/src/plugins/plugin-def.h b/src/plugins/plugin-def.h
index 4c59606..b8cdca8 100644
--- a/src/plugins/plugin-def.h
+++ b/src/plugins/plugin-def.h
@@ -45,7 +45,7 @@ typedef uint32_t plugin_abi_version_t;
 #define GET_ABI_MIN_VERSION(vs) ((vs >> 16) & 0xff)
 #define GET_ABI_REV_VERSION(vs) (vs & 0xffff)
 
-#define CURRENT_ABI_VERSION DEFINE_PLUGIN_ABI_VERSION(0, 1, 0)
+#define CURRENT_ABI_VERSION DEFINE_PLUGIN_ABI_VERSION(0, 2, 0)
 
 //#define HARD_CODE_CURRENT_ABI_VERSION const plugin_abi_version_t abi_version = CURRENT_ABI_VERSION
 
@@ -223,6 +223,7 @@ typedef struct _plugin_interface
     uint64_t magic;                         /* Vérification a minima       */
     plugin_abi_version_t abi_version;       /* Version du protocole utilisé*/
 
+    const char *gtp_name;                   /* Désignation du GType associé*/
     const char *name;                       /* Désignation humaine courte  */
     const char *desc;                       /* Description plus loquace    */
     const char *version;                    /* Version du greffon          */
@@ -253,12 +254,13 @@ typedef struct _plugin_interface
 #define RL(...) BUILD_PG_LIST(.required, ((const char *[]){ __VA_ARGS__ }))
 
 
-#define DEFINE_CHRYSALIDE_PLUGIN(n, d, v, r, a)                 \
+#define DEFINE_CHRYSALIDE_PLUGIN(t, n, d, v, r, a)              \
 G_MODULE_EXPORT const plugin_interface _chrysalide_plugin = {   \
                                                                 \
     .magic = CHRYSALIDE_PLUGIN_MAGIC,                           \
     .abi_version = CURRENT_ABI_VERSION,                         \
                                                                 \
+    .gtp_name = t,                                              \
     .name = n,                                                  \
     .desc = d,                                                  \
     .version = v,                                               \
@@ -271,12 +273,13 @@ G_MODULE_EXPORT const plugin_interface _chrysalide_plugin = {   \
                                                                 \
 }
 
-#define DEFINE_CHRYSALIDE_CONTAINER_PLUGIN(n, d, v, r, a)       \
+#define DEFINE_CHRYSALIDE_CONTAINER_PLUGIN(t, n, d, v, r, a)    \
 G_MODULE_EXPORT const plugin_interface _chrysalide_plugin = {   \
                                                                 \
     .magic = CHRYSALIDE_PLUGIN_MAGIC,                           \
     .abi_version = CURRENT_ABI_VERSION,                         \
                                                                 \
+    .gtp_name = t,                                              \
     .name = n,                                                  \
     .desc = d,                                                  \
     .version = v,                                               \
@@ -291,8 +294,8 @@ G_MODULE_EXPORT const plugin_interface _chrysalide_plugin = {   \
 
 
 /* Interfaçage primaire avec Chrysalide */
-#define DEFINE_CHRYSALIDE_ACTIVE_PLUGIN(n, d, v, ...)   \
-    DEFINE_CHRYSALIDE_PLUGIN(n, d, v, EMPTY_PG_LIST(.required), AL( __VA_ARGS__ ))
+#define DEFINE_CHRYSALIDE_ACTIVE_PLUGIN(t, n, d, v, ...) \
+    DEFINE_CHRYSALIDE_PLUGIN(t, n, d, v, EMPTY_PG_LIST(.required), AL( __VA_ARGS__ ))
 
 
 
diff --git a/src/plugins/plugin-int.h b/src/plugins/plugin-int.h
index 2d98217..4746867 100644
--- a/src/plugins/plugin-int.h
+++ b/src/plugins/plugin-int.h
@@ -83,6 +83,14 @@ struct _GPluginModule
 
     bitfield_t *dependencies;               /* Cartographie des dépendances*/
 
+};
+
+
+/* Greffon pour Chrysalide (classe) */
+struct _GPluginModuleClass
+{
+    GObjectClass parent;                    /* A laisser en premier        */
+
     pg_management_fc init;                  /* Procédure d'initialisation  */
     pg_management_fc exit;                  /* Procédure d'extinction      */
 
@@ -104,14 +112,6 @@ struct _GPluginModule
 };
 
 
-/* Greffon pour Chrysalide (classe) */
-struct _GPluginModuleClass
-{
-    GObjectClass parent;                    /* A laisser en premier        */
-
-};
-
-
 /* Présente dans le journal un message simple. */
 void g_plugin_module_log_simple_message(const GPluginModule *, LogMessageType, const char *);
 
diff --git a/src/plugins/plugin.c b/src/plugins/plugin.c
index a9bd9da..ff3db31 100644
--- a/src/plugins/plugin.c
+++ b/src/plugins/plugin.c
@@ -35,6 +35,7 @@
 #include <string.h>
 
 
+#include "dt.h"
 #include "pglist.h"
 #include "plugin-int.h"
 
@@ -52,6 +53,10 @@ static void g_plugin_module_dispose(GPluginModule *);
 /* Procède à la libération totale de la mémoire. */
 static void g_plugin_module_finalize(GPluginModule *);
 
+/* Initialise la classe des greffons d'extension. */
+static void g_plugin_module_init_gclass(GPluginModuleClass *, GModule *);
+
+
 
 /* Indique le type défini pour un greffon. */
 G_DEFINE_TYPE(GPluginModule, g_plugin_module, G_TYPE_OBJECT);
@@ -117,6 +122,7 @@ static void g_plugin_module_dispose(GPluginModule *plugin)
     const plugin_interface *pg_iface;       /* Définition du greffon       */
     size_t i;                               /* Boucle de parcours          */
     GPluginModule *dependency;              /* Module nécessaire           */
+    GPluginModuleClass *class;              /* Classe de l'instance active */
 
     pg_iface = g_plugin_module_get_interface(plugin);
 
@@ -145,11 +151,16 @@ static void g_plugin_module_dispose(GPluginModule *plugin)
 
     }
 
-    if (plugin->exit != NULL)
-        plugin->exit(plugin);
+    class = G_PLUGIN_MODULE_GET_CLASS(plugin);
+
+    if (class->exit != NULL)
+        class->exit(plugin);
 
     if (plugin->module != NULL)
+    {
         g_module_close(plugin->module);
+        plugin->module = NULL;
+    }
 
     G_OBJECT_CLASS(g_plugin_module_parent_class)->dispose(G_OBJECT(plugin));
 
@@ -195,25 +206,26 @@ static void g_plugin_module_finalize(GPluginModule *plugin)
 GPluginModule *g_plugin_module_new(const gchar *filename)
 {
     GPluginModule *result;                  /* Structure à retourner       */
+    GModule *module;                        /* Abstration de manipulation  */
+    const plugin_interface *interface;      /* Déclaration d'interfaçage   */
     plugin_abi_version_t current;           /* Version de l'ABI actuelle   */
+    bool valid;                             /* Statut de validité          */
     size_t i;                               /* Boucle de parcours          */
     uint32_t action;                        /* Identifiant d'une action    */
     uint32_t category;                      /* Catégorie principale        */
     uint32_t sub;                           /* Sous-catégorie visée        */
+    GType gtype;                            /* Nouveau type de greffon     */
 
-    result = g_object_new(G_TYPE_PLUGIN_MODULE, NULL);
-
-    result->filename = strdup(filename);
-
-    result->module = g_module_open(filename, G_MODULE_BIND_LAZY);
-    if (result->module == NULL)
+    module = g_module_open(filename, G_MODULE_BIND_LAZY);
+    if (module == NULL)
     {
         log_variadic_message(LMT_ERROR, 
                              _("Error while loading the plugin candidate '%s' : %s"),
                              filename, g_module_error());
-        goto bad_plugin;
+        goto bad_module;
     }
 
+
 #define load_plugin_symbol(mod, sym, dest)                                          \
     ({                                                                              \
         bool __result;                                                              \
@@ -221,7 +233,7 @@ GPluginModule *g_plugin_module_new(const gchar *filename)
         {                                                                           \
             log_variadic_message(LMT_ERROR,                                         \
                                  _("No '%s' entry in plugin candidate '%s'"),       \
-                                 sym, result->filename);                            \
+                                 sym, filename);                                    \
             __result = false;                                                       \
         }                                                                           \
         else __result = true;                                                       \
@@ -231,12 +243,12 @@ GPluginModule *g_plugin_module_new(const gchar *filename)
 
     /* Récupération de la version d'ABI */
 
-    if (!load_plugin_symbol(result->module, "_chrysalide_plugin", &result->interface))
+    if (!load_plugin_symbol(module, "_chrysalide_plugin", &interface))
         goto bad_plugin;
 
     current = CURRENT_ABI_VERSION;
 
-    if (current != result->interface->abi_version)
+    if (current != interface->abi_version)
     {
         log_variadic_message(LMT_ERROR, 
                              _("ABI mismatch detected! Plugin '%s' rejected"),
@@ -247,9 +259,20 @@ GPluginModule *g_plugin_module_new(const gchar *filename)
 
     /* Localisation des différents points d'entrée déclarés */
 
-    for (i = 0; i < result->interface->actions_count; i++)
+
+#define check_plugin_symbol(mod, sym)                               \
+    ({                                                              \
+        bool __result;                                              \
+        __result = g_module_symbol(mod, sym, (gpointer []) { 0 });  \
+        __result;                                                   \
+    })
+
+
+    valid = true;
+
+    for (i = 0; i < interface->actions_count && valid; i++)
     {
-        action = result->interface->actions[i];
+        action = interface->actions[i];
         category = MASK_PLUGIN_CATEGORY(action);
         sub = MASK_PLUGIN_SUB_CATEGORY(action);
 
@@ -267,21 +290,17 @@ GPluginModule *g_plugin_module_new(const gchar *filename)
                         switch (action)
                         {
                             case PGA_PLUGIN_INIT:
-                                if (!load_plugin_symbol(result->module,
-                                                        "chrysalide_plugin_init", &result->init))
-                                    goto bad_plugin;
+                                valid = check_plugin_symbol(module, "chrysalide_plugin_init");
                                 break;
 
                             case PGA_PLUGIN_EXIT:
-                                if (!load_plugin_symbol(result->module,
-                                                        "chrysalide_plugin_exit", &result->exit))
-                                    goto bad_plugin;
+                                valid = check_plugin_symbol(module, "chrysalide_plugin_exit");
                                 break;
 
                             default:
                                 log_variadic_message(LMT_WARNING,
                                                      _("Unknown action '0x%02x' in plugin '%s'..."),
-                                                     result->interface->actions[i], filename);
+                                                     interface->actions[i], filename);
                                 break;
 
                         }
@@ -293,16 +312,13 @@ GPluginModule *g_plugin_module_new(const gchar *filename)
                         switch (action)
                         {
                             case PGA_NATIVE_LOADED:
-                                if (!load_plugin_symbol(result->module,
-                                                        "chrysalide_plugin_on_native_loaded",
-                                                        &result->native_loaded))
-                                    goto bad_plugin;
+                                valid = check_plugin_symbol(module, "chrysalide_plugin_on_native_loaded");
                                 break;
 
                             default:
                                 log_variadic_message(LMT_WARNING,
                                                      _("Unknown action '0x%02x' in plugin '%s'..."),
-                                                     result->interface->actions[i], filename);
+                                                     interface->actions[i], filename);
                                 break;
 
                         }
@@ -327,15 +343,13 @@ GPluginModule *g_plugin_module_new(const gchar *filename)
                         switch (action)
                         {
                             case PGA_GUI_THEME:
-                                if (!load_plugin_symbol(result->module,
-                                                        "chrysalide_plugin_include_theme", &result->include_theme))
-                                    goto bad_plugin;
+                                valid = check_plugin_symbol(module, "chrysalide_plugin_include_theme");
                                 break;
 
                             default:
                                 log_variadic_message(LMT_WARNING,
                                                      _("Unknown action '0x%02x' in plugin '%s'..."),
-                                                     result->interface->actions[i], filename);
+                                                     interface->actions[i], filename);
                                 break;
 
                         }
@@ -361,23 +375,17 @@ GPluginModule *g_plugin_module_new(const gchar *filename)
                         {
                             case PGA_CONTENT_EXPLORER:
                             case PGA_CONTENT_RESOLVER:
-                                if (!load_plugin_symbol(result->module,
-                                                        "chrysalide_plugin_handle_binary_content",
-                                                        &result->handle_content))
-                                    goto bad_plugin;
+                                valid = check_plugin_symbol(module, "chrysalide_plugin_handle_binary_content");
                                 break;
 
                             case PGA_CONTENT_ANALYZED:
-                                if (!load_plugin_symbol(result->module,
-                                                        "chrysalide_plugin_handle_loaded_content",
-                                                        &result->handle_loaded))
-                                    goto bad_plugin;
+                                valid = check_plugin_symbol(module, "chrysalide_plugin_handle_loaded_content");
                                 break;
 
                             default:
                                 log_variadic_message(LMT_WARNING,
                                                      _("Unknown action '0x%02x' in plugin '%s'..."),
-                                                     result->interface->actions[i], filename);
+                                                     interface->actions[i], filename);
                                 break;
 
                         }
@@ -392,28 +400,21 @@ GPluginModule *g_plugin_module_new(const gchar *filename)
                             case PGA_FORMAT_ANALYSIS_ENDED:
                             case PGA_FORMAT_POST_ANALYSIS_STARTED:
                             case PGA_FORMAT_POST_ANALYSIS_ENDED:
-                                if (!load_plugin_symbol(result->module,
-                                                        "handle_binary_format_analysis",
-                                                        &result->handle_fmt_analysis))
-                                    goto bad_plugin;
+                                valid = check_plugin_symbol(module, "handle_binary_format_analysis");
                                 break;
 
                             case PGA_FORMAT_PRELOAD:
-                                if (!load_plugin_symbol(result->module,
-                                                        "preload_binary_format", &result->preload_format))
-                                    goto bad_plugin;
+                                valid = check_plugin_symbol(module, "preload_binary_format");
                                 break;
 
                             case PGA_FORMAT_ATTACH_DEBUG:
-                                if (!load_plugin_symbol(result->module,
-                                                        "chrysalide_plugin_attach_debug", &result->attach_debug))
-                                    goto bad_plugin;
+                                valid = check_plugin_symbol(module, "chrysalide_plugin_attach_debug");
                                 break;
 
                             default:
                                 log_variadic_message(LMT_WARNING,
                                                      _("Unknown action '0x%02x' in plugin '%s'..."),
-                                                     result->interface->actions[i], filename);
+                                                     interface->actions[i], filename);
                                 break;
 
                         }
@@ -421,15 +422,11 @@ GPluginModule *g_plugin_module_new(const gchar *filename)
                         break;
 
                     case DPS_DISASSEMBLY:
-                        if (!load_plugin_symbol(result->module,
-                                                "process_binary_disassembly", &result->process_disass))
-                            goto bad_plugin;
+                        valid = check_plugin_symbol(module, "process_binary_disassembly");
                         break;
 
                     case DPS_DETECTION:
-                        if (!load_plugin_symbol(result->module,
-                                                "chrysalide_plugin_detect_external_tools", &result->detect))
-                            goto bad_plugin;
+                        valid = check_plugin_symbol(module, "chrysalide_plugin_detect_external_tools");
                         break;
 
                     default:
@@ -450,11 +447,29 @@ GPluginModule *g_plugin_module_new(const gchar *filename)
 
     }
 
+    if (!valid)
+        goto bad_plugin;
+
+    gtype = built_dynamic_type(G_TYPE_PLUGIN_MODULE, interface->gtp_name,
+                               (GClassInitFunc)g_plugin_module_init_gclass, module);
+
+    if (gtype == G_TYPE_INVALID)
+        goto bad_plugin;
+
+    result = g_object_new(gtype, NULL);
+
+    result->filename = strdup(filename);
+    result->module = module;
+
+    result->interface = interface;
+
     return result;
 
  bad_plugin:
 
-    g_object_unref(G_OBJECT(result));
+    g_module_close(module);
+
+ bad_module:
 
     return NULL;
 
@@ -463,6 +478,212 @@ GPluginModule *g_plugin_module_new(const gchar *filename)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : class  = classe à initialiser.                               *
+*                module = module représentant le greffon chargé en mémoire.   *
+*                                                                             *
+*  Description : Initialise la classe des greffons d'extension.               *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_plugin_module_init_gclass(GPluginModuleClass *class, GModule *module)
+{
+    const plugin_interface *interface;      /* Déclaration d'interfaçage   */
+    size_t i;                               /* Boucle de parcours          */
+    uint32_t action;                        /* Identifiant d'une action    */
+    uint32_t category;                      /* Catégorie principale        */
+    uint32_t sub;                           /* Sous-catégorie visée        */
+
+
+#undef load_plugin_symbol
+
+#define load_plugin_symbol(mod, sym, dest)                          \
+    ({                                                              \
+        bool __result;                                              \
+        __result = g_module_symbol(mod, sym, (gpointer *)dest);     \
+        assert(__result);                                           \
+        __result;                                                   \
+    })
+
+
+    load_plugin_symbol(module, "_chrysalide_plugin", &interface);
+
+    for (i = 0; i < interface->actions_count; i++)
+    {
+        action = interface->actions[i];
+        category = MASK_PLUGIN_CATEGORY(action);
+        sub = MASK_PLUGIN_SUB_CATEGORY(action);
+
+        switch (category)
+        {
+            case DPC_BASIC:
+
+                switch (sub)
+                {
+                    case DPS_NONE:
+                        break;
+
+                    case DPS_PG_MANAGEMENT:
+
+                        switch (action)
+                        {
+                            case PGA_PLUGIN_INIT:
+                                load_plugin_symbol(module, "chrysalide_plugin_init", &class->init);
+                                break;
+
+                            case PGA_PLUGIN_EXIT:
+                                load_plugin_symbol(module, "chrysalide_plugin_exit", &class->exit);
+                                break;
+
+                            default:
+                                assert(false);
+                                break;
+
+                        }
+
+                        break;
+
+                    case DPS_CORE_MANAGEMENT:
+
+                        switch (action)
+                        {
+                            case PGA_NATIVE_LOADED:
+                                load_plugin_symbol(module, "chrysalide_plugin_on_native_loaded",
+                                                   &class->native_loaded);
+                                break;
+
+                            default:
+                                assert(false);
+                                break;
+
+                        }
+
+                        break;
+
+                    default:
+                        assert(false);
+                        break;
+
+                }
+
+                break;
+
+            case DPC_GUI:
+
+                switch (sub)
+                {
+                    case DPS_SETUP:
+
+                        switch (action)
+                        {
+                            case PGA_GUI_THEME:
+                                load_plugin_symbol(module, "chrysalide_plugin_include_theme",
+                                                   &class->include_theme);
+                                break;
+
+                            default:
+                                assert(false);
+                                break;
+
+                        }
+
+                        break;
+
+                    default:
+                        assert(false);
+                        break;
+
+                }
+
+                break;
+
+            case DPC_BINARY_PROCESSING:
+
+                switch (sub)
+                {
+                    case DPS_CONTENT:
+
+                        switch (action)
+                        {
+                            case PGA_CONTENT_EXPLORER:
+                            case PGA_CONTENT_RESOLVER:
+                                load_plugin_symbol(module, "chrysalide_plugin_handle_binary_content",
+                                                   &class->handle_content);
+                                break;
+
+                            case PGA_CONTENT_ANALYZED:
+                                load_plugin_symbol(module, "chrysalide_plugin_handle_loaded_content",
+                                                   &class->handle_loaded);
+                                break;
+
+                            default:
+                                assert(false);
+                                break;
+
+                        }
+
+                        break;
+
+                    case DPS_FORMAT:
+
+                        switch (action)
+                        {
+                            case PGA_FORMAT_ANALYSIS_STARTED:
+                            case PGA_FORMAT_ANALYSIS_ENDED:
+                            case PGA_FORMAT_POST_ANALYSIS_STARTED:
+                            case PGA_FORMAT_POST_ANALYSIS_ENDED:
+                                load_plugin_symbol(module, "handle_binary_format_analysis",
+                                                   &class->handle_fmt_analysis);
+                                break;
+
+                            case PGA_FORMAT_PRELOAD:
+                                load_plugin_symbol(module, "preload_binary_format", &class->preload_format);
+                                break;
+
+                            case PGA_FORMAT_ATTACH_DEBUG:
+                                load_plugin_symbol(module, "chrysalide_plugin_attach_debug", &class->attach_debug);
+                                break;
+
+                            default:
+                                assert(false);
+                                break;
+
+                        }
+
+                        break;
+
+                    case DPS_DISASSEMBLY:
+                        load_plugin_symbol(module, "process_binary_disassembly", &class->process_disass);
+                        break;
+
+                    case DPS_DETECTION:
+                        load_plugin_symbol(module, "chrysalide_plugin_detect_external_tools", &class->detect);
+                        break;
+
+                    default:
+                        assert(false);
+                        break;
+
+                }
+
+                break;
+
+            default:
+                assert(false);
+                break;
+
+        }
+
+    }
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : plugin = greffon à consulter.                                *
 *                                                                             *
 *  Description : Indique le fichier contenant le greffon manipulé.            *
@@ -654,6 +875,7 @@ bool g_plugin_module_load(GPluginModule *plugin, GPluginModule **list, size_t co
     const plugin_interface *pg_iface;       /* Définition du greffon       */
     size_t i;                               /* Boucle de parcours          */
     GPluginModule *dependency;              /* Module nécessaire           */
+    GPluginModuleClass *class;              /* Classe de l'instance active */
     char *dir;                              /* Répertoire modifiable       */
 
     /* Si un essai précédent a déjà échoué ou réussi... */
@@ -689,9 +911,11 @@ bool g_plugin_module_load(GPluginModule *plugin, GPluginModule **list, size_t co
 
     if (result)
     {
-        if (plugin->init != NULL)
+        class = G_PLUGIN_MODULE_GET_CLASS(plugin);
+
+        if (class->init != NULL)
         {
-            result = plugin->init(plugin);
+            result = class->init(plugin);
 
             if (!result)
             {
@@ -810,7 +1034,11 @@ void g_plugin_module_log_variadic_message(const GPluginModule *plugin, LogMessag
 
 void g_plugin_module_notify_native_loaded(GPluginModule *plugin, PluginAction action, void *unused)
 {
-    plugin->native_loaded(plugin, action);
+    GPluginModuleClass *class;              /* Classe de l'instance active */
+
+    class = G_PLUGIN_MODULE_GET_CLASS(plugin);
+
+    class->native_loaded(plugin, action);
 
 }
 
@@ -832,7 +1060,11 @@ void g_plugin_module_notify_native_loaded(GPluginModule *plugin, PluginAction ac
 
 void g_plugin_module_include_theme(const GPluginModule *plugin, PluginAction action, char ***resources, size_t *count)
 {
-    plugin->include_theme(plugin, action, resources, count);
+    GPluginModuleClass *class;              /* Classe de l'instance active */
+
+    class = G_PLUGIN_MODULE_GET_CLASS(plugin);
+
+    class->include_theme(plugin, action, resources, count);
 
 }
 
@@ -855,7 +1087,11 @@ void g_plugin_module_include_theme(const GPluginModule *plugin, PluginAction act
 
 void g_plugin_module_handle_binary_content(const GPluginModule *plugin, PluginAction action, GBinContent *content, wgroup_id_t wid, GtkStatusStack *status)
 {
-    return plugin->handle_content(plugin, action, content, wid, status);
+    GPluginModuleClass *class;              /* Classe de l'instance active */
+
+    class = G_PLUGIN_MODULE_GET_CLASS(plugin);
+
+    class->handle_content(plugin, action, content, wid, status);
 
 }
 
@@ -878,7 +1114,11 @@ void g_plugin_module_handle_binary_content(const GPluginModule *plugin, PluginAc
 
 void g_plugin_module_handle_loaded_content(const GPluginModule *plugin, PluginAction action, GLoadedContent *content, wgroup_id_t wid, GtkStatusStack *status)
 {
-    return plugin->handle_loaded(plugin, action, content, wid, status);
+    GPluginModuleClass *class;              /* Classe de l'instance active */
+
+    class = G_PLUGIN_MODULE_GET_CLASS(plugin);
+
+    return class->handle_loaded(plugin, action, content, wid, status);
 
 }
 
@@ -901,7 +1141,11 @@ void g_plugin_module_handle_loaded_content(const GPluginModule *plugin, PluginAc
 
 bool g_plugin_module_handle_binary_format_analysis(const GPluginModule *plugin, PluginAction action, GBinFormat *format, wgroup_id_t gid, GtkStatusStack *status)
 {
-    return plugin->handle_fmt_analysis(plugin, action, format, gid, status);
+    GPluginModuleClass *class;              /* Classe de l'instance active */
+
+    class = G_PLUGIN_MODULE_GET_CLASS(plugin);
+
+    return class->handle_fmt_analysis(plugin, action, format, gid, status);
 
 }
 
@@ -924,7 +1168,11 @@ bool g_plugin_module_handle_binary_format_analysis(const GPluginModule *plugin,
 
 bool g_plugin_module_preload_binary_format(const GPluginModule *plugin, PluginAction action, GBinFormat *format, GPreloadInfo *info, GtkStatusStack *status)
 {
-    return plugin->preload_format(plugin, action, format, info, status);
+    GPluginModuleClass *class;              /* Classe de l'instance active */
+
+    class = G_PLUGIN_MODULE_GET_CLASS(plugin);
+
+    return class->preload_format(plugin, action, format, info, status);
 
 }
 
@@ -945,7 +1193,11 @@ bool g_plugin_module_preload_binary_format(const GPluginModule *plugin, PluginAc
 
 void g_plugin_module_attach_debug_format(const GPluginModule *plugin, PluginAction action, GExeFormat *format)
 {
-    plugin->attach_debug(plugin, action, format);
+    GPluginModuleClass *class;              /* Classe de l'instance active */
+
+    class = G_PLUGIN_MODULE_GET_CLASS(plugin);
+
+    class->attach_debug(plugin, action, format);
 
 }
 
@@ -968,7 +1220,11 @@ void g_plugin_module_attach_debug_format(const GPluginModule *plugin, PluginActi
 
 void g_plugin_module_process_disassembly_event(const GPluginModule *plugin, PluginAction action, GLoadedBinary *binary, GtkStatusStack *status, GProcContext *context)
 {
-    plugin->process_disass(plugin, action, binary, status, context);
+    GPluginModuleClass *class;              /* Classe de l'instance active */
+
+    class = G_PLUGIN_MODULE_GET_CLASS(plugin);
+
+    class->process_disass(plugin, action, binary, status, context);
 
 }
 
@@ -992,6 +1248,10 @@ void g_plugin_module_process_disassembly_event(const GPluginModule *plugin, Plug
 
 void g_plugin_module_detect_external_tools(const GPluginModule *plugin, PluginAction action, const GLoadedContent *content, bool version, char ***names, size_t *count)
 {
-    plugin->detect(plugin, action, content, version, names, count);
+    GPluginModuleClass *class;              /* Classe de l'instance active */
+
+    class = G_PLUGIN_MODULE_GET_CLASS(plugin);
+
+    class->detect(plugin, action, content, version, names, count);
 
 }
diff --git a/src/plugins/plugin.h b/src/plugins/plugin.h
index 4b3b306..cccd39b 100644
--- a/src/plugins/plugin.h
+++ b/src/plugins/plugin.h
@@ -59,12 +59,12 @@ typedef enum _PluginStatusFlags
 #define BROKEN_PLUGIN_STATUS (PSF_UNKNOW_DEP | PSF_DEP_LOOP | PSF_FAILURE)
 
 
-#define G_TYPE_PLUGIN_MODULE                (g_plugin_module_get_type())
-#define G_PLUGIN_MODULE(obj)                (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_PLUGIN_MODULE, GPluginModule))
-#define G_IS_PLUGIN_MODULE(obj)             (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_PLUGIN_MODULE))
-#define G_PLUGIN_MODULE_CLASS(klass)        (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_PLUGIN_MODULE, GPluginModuleClass))
-#define G_IS_PLUGIN_MODULE_CLASS(klass)     (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_PLUGIN_MODULE))
-#define G_PLUGIN_MODULE_GET_CLASS(obj)      (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_PLUGIN_MODULE, GPluginModuleClass))
+#define G_TYPE_PLUGIN_MODULE            (g_plugin_module_get_type())
+#define G_PLUGIN_MODULE(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_PLUGIN_MODULE, GPluginModule))
+#define G_IS_PLUGIN_MODULE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_PLUGIN_MODULE))
+#define G_PLUGIN_MODULE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_PLUGIN_MODULE, GPluginModuleClass))
+#define G_IS_PLUGIN_MODULE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_PLUGIN_MODULE))
+#define G_PLUGIN_MODULE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_PLUGIN_MODULE, GPluginModuleClass))
 
 
 /* Indique le type défini pour un greffon. */
diff --git a/tests/plugins/__init__.py b/tests/plugins/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/plugins/plugin.py b/tests/plugins/plugin.py
new file mode 100644
index 0000000..6409975
--- /dev/null
+++ b/tests/plugins/plugin.py
@@ -0,0 +1,223 @@
+#!/usr/bin/python3-dbg
+# -*- coding: utf-8 -*-
+
+
+from chrysacase import ChrysalideTestCase
+from pychrysalide import PluginModule
+import gc
+
+
+class TestPlugin(ChrysalideTestCase):
+    """TestCase for GPluginModule."""
+
+
+    def testGarbageCollecting(self):
+        """Ensure the garbarge collector is working for plugin modules."""
+
+
+        class MyPG_1(PluginModule):
+
+            def __init__(self):
+
+                interface = {
+                    'name' : 'some_name',
+                    'desc' : 'Provide some information about the useless plugin',
+                    'version' : '0.1',
+                    'actions' : ( )
+                }
+
+                super(MyPG_1, self).__init__(**interface)
+
+
+        pg = MyPG_1()
+        self.assertIsNotNone(pg)
+
+
+        class MyPG_2(PluginModule):
+
+            def __init__(self):
+
+                interface = {
+                    'name' : 'some_name',
+                    'desc' : 'Provide some information about the useless plugin',
+                    'version' : '0.1',
+                    'actions' : ( )
+                }
+
+                super(MyPG_2, self).__init__(**interface)
+
+
+        pg = MyPG_2()
+        self.assertIsNotNone(pg)
+
+
+        class MyPG_3(PluginModule):
+
+            def __init__(self):
+
+                interface = {
+                    'name' : 'some_name',
+                    'desc' : 'Provide some information about the useless plugin',
+                    'version' : '0.1',
+                    'actions' : ( )
+                }
+
+                super(MyPG_3, self).__init__(**interface)
+
+
+        pg = MyPG_3()
+        self.assertIsNotNone(pg)
+
+
+        class MyPG_4(PluginModule):
+
+            def __init__(self):
+
+                interface = {
+                    'name' : 'some_name',
+                    'desc' : 'Provide some information about the useless plugin',
+                    'version' : '0.1',
+                    'actions' : ( )
+                }
+
+                super(MyPG_4, self).__init__(**interface)
+
+
+        pg = MyPG_4()
+        self.assertIsNotNone(pg)
+
+
+        class MyPG_5(PluginModule):
+
+            def __init__(self):
+
+                interface = {
+                    'name' : 'some_name',
+                    'desc' : 'Provide some information about the useless plugin',
+                    'version' : '0.1',
+                    'actions' : ( )
+                }
+
+                super(MyPG_5, self).__init__(**interface)
+
+
+        pg = MyPG_5()
+        self.assertIsNotNone(pg)
+
+
+        gc.collect()
+
+
+    def testCreation(self):
+        """Validate PluginModule creation from Python."""
+
+
+        class MyPG_0(PluginModule):
+            pass
+
+
+        # TypeError: Required argument 'name' (pos 1) not found
+        with self.assertRaises(TypeError):
+            pg = MyPG_0()
+
+
+        class MyPG_1(PluginModule):
+
+            def __init__(self):
+
+                interface = {
+                    'name' : 'some_name',
+                    'desc' : 'Provide some information about the useless plugin',
+                    'version' : '0.1',
+                    'actions' : ( )
+                }
+
+                super(MyPG_1, self).__init__(**interface)
+
+
+        pg = MyPG_1()
+        self.assertIsNotNone(pg)
+
+
+        class MyPG_2(PluginModule):
+
+            def __init__(self):
+
+                interface = {
+                    'name' : 'some_name',
+                    'desc' : 'Provide some information about the useless plugin',
+                    'version' : '0.1',
+                    'actions' : ( 'ABC', )
+                }
+
+                super(MyPG_2, self).__init__(**interface)
+
+
+        # TypeError: Invalid type for plugin action.
+        with self.assertRaises(TypeError):
+            pg = MyPG_2()
+
+
+        class MyPG_3(PluginModule):
+
+            def __init__(self):
+
+                interface = {
+                    'name' : 'some_name',
+                    'desc' : 'Provide some information about the useless plugin',
+                    'version' : '0.1',
+                    'actions' : ( PluginModule.PGA_CONTENT_EXPLORER, )
+                }
+
+                super(MyPG_3, self).__init__(**interface)
+
+
+        # TypeError: missing features for the declared actions.
+        with self.assertRaises(TypeError):
+            pg = MyPG_3()
+
+
+        class MyPG_4(PluginModule):
+
+            def __init__(self):
+
+                interface = {
+                    'name' : 'some_name4',
+                    'desc' : 'Provide some information about the useless plugin',
+                    'version' : '0.1',
+                    'actions' : ( PluginModule.PGA_CONTENT_EXPLORER, )
+                }
+
+                super(MyPG_4, self).__init__(**interface)
+
+            def handle_binary_content(self, action, content, wid, status):
+                pass
+
+
+        pg = MyPG_4()
+        self.assertIsNotNone(pg)
+
+
+    def testDoubleUsage(self):
+        """Validate PluginModule double usage in Python."""
+
+
+        class MyPG(PluginModule):
+
+            def __init__(self):
+
+                interface = {
+                    'name' : 'some_name',
+                    'desc' : 'Provide some information about the useless plugin',
+                    'version' : '0.1',
+                    'actions' : ( )
+                }
+
+                super(MyPG, self).__init__(**interface)
+
+
+        pg1 = MyPG()
+        self.assertIsNotNone(pg1)
+
+        pg2 = MyPG()
+        self.assertIsNotNone(pg2)
-- 
cgit v0.11.2-87-g4458