summaryrefslogtreecommitdiff
path: root/src/glibext/signal.c
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2014-07-28 21:12:51 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2014-07-28 21:12:51 (GMT)
commitee9bbfc34d86bfcf9384ed93e4300f6464528b9b (patch)
tree3efcb8bf919198126c80eae0532c731e25703cc7 /src/glibext/signal.c
parent250d2773aa372434b721a4e72bff5da7b4f3fb4e (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
Diffstat (limited to 'src/glibext/signal.c')
-rw-r--r--src/glibext/signal.c171
1 files changed, 171 insertions, 0 deletions
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);
+
+}