summaryrefslogtreecommitdiff
path: root/src/glibext/signal.c
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2025-04-16 12:26:41 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2025-04-16 12:26:41 (GMT)
commitf0e32b052f0ea1d9cdc7074b933a5ddcd85ef721 (patch)
tree90e85b977ab915f50852770c9197914cdadbcfe6 /src/glibext/signal.c
parentfc5e23a8d2fe7457c14ac5e5ceeff2e8d40d7f3a (diff)
Restore the glue allowing to redirect signals to the main thread.
Diffstat (limited to 'src/glibext/signal.c')
-rw-r--r--src/glibext/signal.c155
1 files changed, 110 insertions, 45 deletions
diff --git a/src/glibext/signal.c b/src/glibext/signal.c
index 33290fb..ee8daed 100644
--- a/src/glibext/signal.c
+++ b/src/glibext/signal.c
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* signal.c - encadrement des signaux supplémentaire par rapport à celui de la GLib
*
- * Copyright (C) 2014-2018 Cyrille Bagard
+ * Copyright (C) 2014-2025 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -28,42 +28,48 @@
#include <malloc.h>
#include <stdarg.h>
#include <stdbool.h>
+#include <gobject/gclosure.h>
#include <gobject/gvaluecollector.h>
-/* Prototype pour le transfert d'exécution. */
-typedef void (* GSignalCallback) (gpointer, ...);
+/* Informations utiles à l'appel final */
+typedef struct _gsignal_wrapper_params_t
+{
+ GClosure *closure; /* Glue pour les appels */
+
+ guint n_params; /* Nombre de paramètres */
+ GValue instance_and_params[0]; /* Instance & paramètres */
+
+} gsignal_wrapper_params_t;
+
+/* Transmet un signal dans le contexte principal. */
+static gboolean to_main_wrapper(gpointer);
+/* Supprime de la mémoire le transporteur d'informations. */
+static void destroy_wrapper_params(gpointer);
/* Informations concernant une diffusion de signal */
-typedef struct _gsignal_wrapper_info
+typedef struct _gsignal_wrapper_info_t
{
gpointer instance; /* Instance GLib initiatrice */
+ gulong id; /* Identifiant de connexion */
GClosure *closure; /* Glue pour les appels */
- GType return_type; /* Type de la valeur retournée */
guint n_params; /* Nombre de paramètres */
- const GType *param_types; /* Type des paramètres associés*/
+ GType param_types[0]; /* Type des paramètres associés*/
- GValue return_value; /* Valeur de retour */
- GValue instance_and_params[0]; /* Instance & paramètres */
-
-} gsignal_wrapper_info;
-
-
-/* Transmet un signal dans le contexte principal. */
-static gboolean to_main_wrapper(gsignal_wrapper_info *);
+} gsignal_wrapper_info_t;
/* Réceptionne un signal et redirige son exécution. */
-static void carry_signal_to_main_thread(gsignal_wrapper_info *, ...);
+static void carry_signal_to_main_thread(gsignal_wrapper_info_t *, ...);
/******************************************************************************
* *
-* Paramètres : info = collecteur d'informations sur la diffusion. *
+* Paramètres : data = collecteur d'informations sur la diffusion. *
* *
* Description : Transmet un signal dans le contexte principal. *
* *
@@ -73,11 +79,17 @@ static void carry_signal_to_main_thread(gsignal_wrapper_info *, ...);
* *
******************************************************************************/
-static gboolean to_main_wrapper(gsignal_wrapper_info *info)
+static gboolean to_main_wrapper(gpointer data)
{
- g_closure_invoke(info->closure, NULL/*&info->return_value*/,
- info->n_params + 1, info->instance_and_params,
- NULL);
+ gsignal_wrapper_params_t *params; /* Informations d'appel */
+
+ params = (gsignal_wrapper_params_t *)data;
+
+ g_closure_invoke(params->closure,
+ NULL /* return_value */,
+ params->n_params + 1,
+ params->instance_and_params,
+ NULL /* invocation_hint */);
return G_SOURCE_REMOVE;
@@ -86,6 +98,35 @@ static gboolean to_main_wrapper(gsignal_wrapper_info *info)
/******************************************************************************
* *
+* Paramètres : data = collecteur d'informations à supprimer. *
+* *
+* Description : Supprime de la mémoire le transporteur d'informations. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void destroy_wrapper_params(gpointer data)
+{
+ gsignal_wrapper_params_t *params; /* Informations d'appel */
+ guint i; /* Boucle de parcours */
+
+ params = (gsignal_wrapper_params_t *)data;
+
+ g_closure_unref(params->closure);
+
+ for (i = 0; i < (params->n_params + 1); i++)
+ g_value_unset(params->instance_and_params + i);
+
+ free(params);
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : info = collecteur d'informations sur la diffusion. *
* ... = arguments poussés par la GLib sur la pile. *
* *
@@ -97,23 +138,26 @@ static gboolean to_main_wrapper(gsignal_wrapper_info *info)
* *
******************************************************************************/
-static void carry_signal_to_main_thread(gsignal_wrapper_info *info, ...)
+static void carry_signal_to_main_thread(gsignal_wrapper_info_t *info, ...)
{
+ gsignal_wrapper_params_t *params; /* Informations d'appel */
GValue *param_values; /* Paramètres d'appel */
va_list ap; /* Liste d'arguments sur pile */
guint i; /* Boucle de parcours */
bool static_scope; /* Portée des arguments */
gchar *error; /* Eventuelle erreur inattendue*/
- //g_value_init(&info->return_value, info->return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE);
+ params = calloc(1, sizeof(gsignal_wrapper_params_t) + sizeof(GValue) * (info->n_params + 1));
+
+ params->closure = info->closure;
+ g_closure_ref(info->closure);
- if (G_IS_VALUE(info->instance_and_params))
- g_value_unset(info->instance_and_params);
+ params->n_params = info->n_params;
- g_value_init(info->instance_and_params, G_TYPE_FROM_INSTANCE(info->instance));
- g_value_set_instance(info->instance_and_params, info->instance);
+ g_value_init(params->instance_and_params, G_TYPE_FROM_INSTANCE(info->instance));
+ g_value_set_instance(params->instance_and_params, info->instance);
- param_values = info->instance_and_params + 1;
+ param_values = params->instance_and_params + 1;
va_start(ap, info);
@@ -121,9 +165,6 @@ static void carry_signal_to_main_thread(gsignal_wrapper_info *info, ...)
for (i = 0; i < info->n_params; i++)
{
- if (G_IS_VALUE(param_values + i))
- g_value_unset(param_values + i);
-
static_scope = info->param_types[i] & G_SIGNAL_TYPE_STATIC_SCOPE;
G_VALUE_COLLECT_INIT(param_values + i,
@@ -143,7 +184,28 @@ static void carry_signal_to_main_thread(gsignal_wrapper_info *info, ...)
va_end(ap);
if (error == NULL)
- g_idle_add_full(G_PRIORITY_HIGH_IDLE, (GSourceFunc)to_main_wrapper, info, NULL);
+ g_idle_add_full(G_PRIORITY_HIGH_IDLE, to_main_wrapper, params, destroy_wrapper_params);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : info = collecteur d'informations à supprimer. *
+* *
+* Description : Déconnecte un signal redirigé vers le contexte principal. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_signal_disconnect_from_main(gsignal_wrapper_info_t *info)
+{
+ g_signal_handler_disconnect(info->instance, info->id);
+
+ free(info);
}
@@ -165,41 +227,44 @@ static void carry_signal_to_main_thread(gsignal_wrapper_info *info, ...)
* *
******************************************************************************/
-gulong _g_signal_connect_to_main(gpointer instance, const gchar *signal, GCallback handler, gpointer data, GClosureMarshal marshal, GConnectFlags flags)
+gsignal_wrapper_info_t *_g_signal_connect_to_main(gpointer instance, const gchar *signal, GCallback handler, gpointer data, GClosureMarshal marshal, GConnectFlags flags)
{
+ gsignal_wrapper_info_t *result; /* Structure à renvoyer */
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);
+
assert(query.signal_id != 0);
+ assert(query.return_type == G_TYPE_NONE);
/* Allocation adaptée */
- info = calloc(1, sizeof(gsignal_wrapper_info) + sizeof(GValue) * (query.n_params + 1));
+ result = malloc(sizeof(gsignal_wrapper_info_t) + sizeof(GType) * query.n_params);
- info->instance = instance;
+ result->instance = instance;
if (flags & G_CONNECT_SWAPPED)
- info->closure = g_cclosure_new_swap(handler, data, NULL);
+ result->closure = g_cclosure_new_swap(handler, data, NULL);
else
- info->closure = g_cclosure_new(handler, data, NULL);
+ result->closure = g_cclosure_new(handler, data, NULL);
- g_closure_ref(info->closure);
- g_closure_sink(info->closure);
+ g_closure_ref(result->closure);
+ g_closure_sink(result->closure);
- g_closure_set_marshal(info->closure, marshal);
+ g_closure_set_marshal(result->closure, marshal);
- info->return_type = query.return_type;
- info->n_params = query.n_params;
- info->param_types = query.param_types;
+ result->n_params = query.n_params;
+ memcpy(result->param_types, query.param_types, sizeof(GType) * query.n_params);
- assert(query.return_type == G_TYPE_NONE);
+ /* Connexion au signal */
+
+ result->id = g_signal_connect_swapped(instance, signal, G_CALLBACK(carry_signal_to_main_thread), result);
- return g_signal_connect_swapped(instance, signal, G_CALLBACK(carry_signal_to_main_thread), info);
+ return result;
}