diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2014-07-28 21:12:51 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2014-07-28 21:12:51 (GMT) |
commit | ee9bbfc34d86bfcf9384ed93e4300f6464528b9b (patch) | |
tree | 3efcb8bf919198126c80eae0532c731e25703cc7 | |
parent | 250d2773aa372434b721a4e72bff5da7b4f3fb4e (diff) |
Provided a way to receive a signal in the main thread.
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@383 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
-rw-r--r-- | ChangeLog | 12 | ||||
-rw-r--r-- | src/glibext/Makefile.am | 1 | ||||
-rw-r--r-- | src/glibext/signal.c | 171 | ||||
-rw-r--r-- | src/glibext/signal.h | 37 | ||||
-rw-r--r-- | src/project.c | 5 |
5 files changed, 224 insertions, 2 deletions
@@ -1,3 +1,15 @@ +14-07-28 Cyrille Bagard <nocbos@gmail.com> + + * src/glibext/Makefile.am: + Add the 'signal.[ch]' files to libglibext_la_SOURCES. + + * src/glibext/signal.c: + * src/glibext/signal.h: + New entries: provide a way to receive a signal in the main thread. + + * src/project.c: + Update code. + 14-07-22 Cyrille Bagard <nocbos@gmail.com> * plugins/pychrysa/gui/editem.c: diff --git a/src/glibext/Makefile.am b/src/glibext/Makefile.am index 50b9902..192587d 100644 --- a/src/glibext/Makefile.am +++ b/src/glibext/Makefile.am @@ -13,6 +13,7 @@ libglibext_la_SOURCES = \ gbuffersegment.h gbuffersegment.c \ gcodebuffer.h gcodebuffer.c \ gnhash.h gnhash.c \ + signal.h signal.c \ proto.h libglibext_la_LDFLAGS = diff --git a/src/glibext/signal.c b/src/glibext/signal.c new file mode 100644 index 0000000..c7c8fe3 --- /dev/null +++ b/src/glibext/signal.c @@ -0,0 +1,171 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * signal.h - prototypes pour un encadrement des signaux supplémentaire par rapport à celui de la GLib + * + * Copyright (C) 2009-2013 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * OpenIDA 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. + * + * OpenIDA 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 Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "signal.h" + + +#include <malloc.h> +#include <stdarg.h> + + + +/* Prototype pour le transfert d'exécution. */ +typedef void (* GSignalCallback) (gpointer, ...); + + +/* Informations concernant une diffusion de signal */ +typedef struct _gsignal_wrapper_info +{ + GConnectFlags flags; /* Ordre des arguments */ + + GSignalCallback callback; /* Fonction finale de récept° */ + gpointer instance; /* Instance GLib initiatrice */ + gpointer data; /* Donnée utilisateur associée */ + + guint n_params; /* Nombre de paramètres */ + unsigned long params[0]; /* Paramètres récupérés */ + +} gsignal_wrapper_info; + + +/* Réceptionne un signal et redirige son exécution. */ +static void carry_signal_to_main_thread(gsignal_wrapper_info *, ...); + +/* Transmet un signal dans le contexte principal. */ +static gboolean to_main_wrapper(gsignal_wrapper_info *); + + + +/****************************************************************************** +* * +* Paramètres : info = collecteur d'informations sur la diffusion. * +* * +* Description : Transmet un signal dans le contexte principal. * +* * +* Retour : FALSE / G_SOURCE_REMOVE pour arrêter la transmission. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static gboolean to_main_wrapper(gsignal_wrapper_info *info) +{ + gpointer data1; /* Premier argument à envoyer */ + gpointer data2; /* Dernier argument à envoyer */ + + if (info->flags & G_CONNECT_SWAPPED) + { + data1 = info->data; + data2 = info->instance; + } + else + { + data1 = info->instance; + data2 = info->data; + } + + switch (info->n_params - 1) + { + case 0: + info->callback(data1, data2); + break; + + } + + return G_SOURCE_REMOVE; + +} + + +/****************************************************************************** +* * +* Paramètres : info = collecteur d'informations sur la diffusion. * +* ... = arguments poussés par la GLib sur la pile. * +* * +* Description : Réceptionne un signal et redirige son exécution. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void carry_signal_to_main_thread(gsignal_wrapper_info *info, ...) +{ + va_list ap; /* Liste d'arguments sur pile */ + guint i; /* Boucle de parcours */ + + va_start(ap, info); + + for (i = 0; i < info->n_params; i++) + info->params[i] = va_arg(ap, unsigned long); + + va_end(ap); + + g_idle_add_full(G_PRIORITY_HIGH_IDLE, (GSourceFunc)to_main_wrapper, info, free); + +} + + +/****************************************************************************** +* * +* Paramètres : instance = object GLib à l'origine de l'émission. * +* signal = identification du signal à réceptionner. * +* handler = fonction C servant de réceptacle. * +* data = éventuelle donnée de l'utilisateur à ajouter. * +* * +* Description : Reproduit le comportement de la fonction g_signal_connect(). * +* * +* Retour : Identifiant supérieur zéro en cas de succès. * +* * +* Remarques : - * +* * +******************************************************************************/ + +gulong g_signal_connect_to_main(gpointer instance, const gchar *signal, GCallback handler, gpointer data) +{ + guint signal_id; /* Identifiant du signal visé */ + GSignalQuery query; /* Information sur le signal */ + gsignal_wrapper_info *info; /* Encapsulation des données */ + + /* Collection d'informations */ + + signal_id = g_signal_lookup(signal, G_TYPE_FROM_INSTANCE(instance)); + + g_signal_query(signal_id, &query); + + /* Allocation adaptée */ + + info = (gsignal_wrapper_info *)malloc(sizeof(gsignal_wrapper_info) + sizeof(unsigned long) * ++query.n_params); + + info->flags = 0; + + info->callback = (GSignalCallback)handler; + info->instance = instance; + info->data = data; + + info->n_params = query.n_params; + + return g_signal_connect_swapped(instance, signal, G_CALLBACK(carry_signal_to_main_thread), info); + +} diff --git a/src/glibext/signal.h b/src/glibext/signal.h new file mode 100644 index 0000000..8d139a7 --- /dev/null +++ b/src/glibext/signal.h @@ -0,0 +1,37 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * signal.h - prototypes pour un encadrement des signaux supplémentaire par rapport à celui de la GLib + * + * Copyright (C) 2009-2012 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * OpenIDA 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. + * + * OpenIDA 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 Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _GLIBEXT_SIGNAL_H +#define _GLIBEXT_SIGNAL_H + + +#include <glib-object.h> + + + +/* Reproduit le comportement de la fonction g_signal_connect(). */ +gulong g_signal_connect_to_main(gpointer, const gchar *, GCallback, gpointer); + + + +#endif /* _GLIBEXT_SIGNAL_H */ diff --git a/src/project.c b/src/project.c index a555f2d..faf232a 100644 --- a/src/project.c +++ b/src/project.c @@ -32,6 +32,7 @@ #include "analysis/binaries/file.h" #include "common/xml.h" #include "core/params.h" +#include "glibext/signal.h" #include "gtkext/easygtk.h" #include "gtkext/gtkblockview.h" #include "gtkext/gtkgraphview.h" @@ -209,8 +210,8 @@ GStudyProject *g_study_project_open(GObject *ref, const char *filename) if (binary != NULL) { - g_signal_connect(binary, "disassembly-done", - G_CALLBACK(g_study_project_add_loaded_binary), result); + g_signal_connect_to_main(binary, "disassembly-done", + G_CALLBACK(g_study_project_add_loaded_binary), result); g_loaded_binary_analyse(binary); } |