"A GClosure represents a callback supplied by the programmer.
It will generally comprise a function of some kind and a marshaller used to call it. It is the responsibility of the marshaller to convert the arguments for the invocation from GValues into a suitable form, perform the callback on the converted arguments, and transform the return value back into a GValue." This is how it is in the documentation.
To test and try it out, I wrote a small program that is intended to use the following structure:
struct GClosure {
guint in_marshal : 1;
guint is_invalid : 1;
void (* marshal) (
GClosure* closure,
GValue* return_value,
guint n_param_values,
const GValue* param_values,
gpointer invocation_hint,
gpointer marshal_data
);
}
My problem is that I have not yet managed to find a way to use "return-value".
Unfortunately, all my previous attempts ended with a memory error.
Here is the Script:
#include<gtk/gtk.h>
typedef struct _MyClosure
{
GClosure closure;
int closure_data;
} MyClosure;
static void
my_closure_finalize(gpointer notify_data, GClosure *closure)
{
MyClosure * my_closure = (MyClosure*)closure;
printf("Finalizing closure with closure_data: %d\n",my_closure->closure_data);
}
GValue* my_callback(GClosure *closure, const GValue *param_values)
{
MyClosure *my_closure = (MyClosure*)closure;
printf("In Callback with closure_data. %d\n", my_closure->closure_data);
if (¶m_values[0] != NULL)
{
printf("In Callback with value: %s\n", g_value_get_string(¶m_values[0]));
}
/* Return */
GValue value = G_VALUE_INIT;
g_value_init(&value, G_TYPE_STRING);
g_value_set_static_string(&value, "The End");
/* edit */
printf("Return from Callback %s\n",g_value_get_string(&value));
return value;
}
static void
my_closure_marshal(GClosure *closure,
GValue *return_value,
guint n_params_values,
const GValue *param_values,
gpointer invocation_hint,
gpointer marshal_data)
{
MyClosure *my_closure = (MyClosure*)closure;
printf("mashalling closure with closure_data. %d\n", my_closure->closure_data);
if (¶m_values[0] != NULL)
{
printf("Callback called with value: %s\n", g_value_get_string(¶m_values[0]));
}
/* edit */
*return_value = my_callback(closure,param_values);
// Segmentation fault (core dumped)
/*
printf("after Callback\n");
GType type = G_VALUE_TYPE(return_value);
g_print("Return type %s\n",g_type_name(type));
g_print("Result in Mashaller %s\n",g_value_get_string(return_value));
*/
}
MyClosure *
my_closure_new(gpointer data)
{
GClosure *closure;
MyClosure *my_closure;
closure = g_closure_new_simple(sizeof(MyClosure), data);
my_closure = (MyClosure*)closure;
my_closure->closure_data = 42;
g_closure_add_finalize_notifier(closure,NULL, my_closure_finalize);
g_closure_set_marshal(closure, my_closure_marshal);
return my_closure;
}
int main(int argc, char* argv[])
{
MyClosure *my_closure = my_closure_new(NULL);
GValue* return_value;
GValue value = G_VALUE_INIT;
g_value_init(&value, G_TYPE_STRING);
g_value_set_string(&value, "Hello");
g_closure_invoke((GClosure*)my_closure,return_value, 1,&value , NULL);
/* How can I further process here "return_value" */
/*It should be the string "The End". */
g_closure_unref((GClosure*)my_closure);
return 0;
}
Does anyone have an idea?
Having edited according to the proposal of 'Bodo', I get the following result:
mashalling closure with closure_data. 42
Callback called with value: Hello
In Callback with closure_data. 42
In Callback with value: Hello
Return from Callback The End
Segmentation fault (core dumped)
After many attempts, I have now succeeded in creating a test program for using GClosure that no longer generates errors.
In addition to the indications from @bodo, it was still important, return_value
before calling g_closure_invoke((GClosure*)my_closure,return_value, 1,&value , NULL);
with
GValue * return_value = g_new0(GValue, 1);
to create.
The whole script now looks like this:
#include<gtk/gtk.h>
typedef struct _MyClosure
{
GClosure closure;
int closure_data;
} MyClosure;
static void
my_closure_finalize(gpointer notify_data, GClosure *closure)
{
MyClosure * my_closure = (MyClosure*)closure;
printf("Finalizing closure with closure_data: %d\n",my_closure->closure_data);
}
gchar *
my_callback(GClosure *closure, const GValue *param_values)
{
MyClosure *my_closure = (MyClosure*)closure;
gchar *result;
printf("Callback use:\n");
printf(" -- closure_data: %d\n", my_closure->closure_data);
if (¶m_values[0] != NULL)
{
printf(" -- &value: %s\n", g_value_get_string(¶m_values[0]));
result = g_strdup_printf("%s %d %s",g_value_get_string(¶m_values[0]) , my_closure->closure_data, "The Ende");
}
else
result = g_strdup_printf("%s" , "The Ende");
/*Return*/
return result;
}
static void
my_closure_marshal(GClosure *closure,
GValue *return_value,
guint n_params_values,
const GValue *param_values,
gpointer invocation_hint,
gpointer marshal_data)
{
MyClosure *my_closure = (MyClosure*)closure;
g_value_init(return_value,G_TYPE_STRING);
gchar *result = my_callback((GClosure*)my_closure,param_values);
g_value_set_string(return_value,result);
}
MyClosure *
my_closure_new(int data)
{
GClosure *closure;
MyClosure *my_closure;
closure = g_closure_new_simple(sizeof(MyClosure), &data);
my_closure = (MyClosure*)closure;
my_closure->closure_data = data;
g_closure_add_finalize_notifier((GClosure*)my_closure,NULL, my_closure_finalize);
g_closure_set_marshal((GClosure*)my_closure, my_closure_marshal);
return my_closure;
}
int main(int argc, char* argv[])
{
MyClosure *my_closure = my_closure_new(42);
GValue * return_value = g_new0(GValue, 1);
GValue value = G_VALUE_INIT;
g_value_init(&value, G_TYPE_STRING);
g_value_set_string(&value, "Hello");
g_closure_invoke((GClosure*)my_closure,return_value, 1,&value , NULL);
g_print("Result: %s\n",g_value_get_string(return_value));
g_value_unset(&value);
g_free(return_value);
g_closure_unref((GClosure*)my_closure);
return 0;
}