1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
|
// gcc gclosure.c -o gclosure `pkg-config --cflags --libs gobject-2.0`
#include <glib-object.h>
typedef void (*MyCallback)(gint arg1, const gchar* arg2, gpointer user_data);
void my_marshal(GClosure* closure,
GValue* return_value,
guint n_param_values,
const GValue* param_values,
gpointer invocation_hint,
gpointer marshal_data)
{
g_return_if_fail(n_param_values == 3);
MyCallback callback;
callback = (MyCallback)g_value_get_pointer(¶m_values[0]);
if (!callback)
return;
gint arg1 = g_value_get_int(¶m_values[1]);
const gchar* arg2 = g_value_get_string(¶m_values[2]);
callback(arg1, arg2, closure->data);
}
void example_callback(gint num, gchar* str, gpointer user_data)
{
g_print("Callback called with: %d, '%s' (user_data: %p)\n",
num, str, user_data);
}
int main()
{
GClosure* closure = g_closure_new_simple(sizeof(GClosure), NULL);
g_print("Initial refcount: %d\n", closure->ref_count);
g_closure_set_marshal(closure, my_marshal);
gpointer user_data = (gpointer)0x3a5000;
closure->data = user_data;
GValue params[3] = { G_VALUE_INIT, G_VALUE_INIT, G_VALUE_INIT };
g_value_init(¶ms[0], G_TYPE_POINTER);
g_value_set_pointer(¶ms[0], example_callback);
g_value_init(¶ms[1], G_TYPE_INT);
g_value_set_int(¶ms[1], 42);
g_value_init(¶ms[2], G_TYPE_STRING);
g_value_set_string(¶ms[2], "Hello GClosure");
GValue return_value = G_VALUE_INIT;
g_closure_invoke(closure, &return_value, 3, params, NULL);
g_closure_ref(closure);
g_print("After ref, refcount: %d\n", closure->ref_count);
g_closure_sink(closure);
g_print("After sinking, refcount: %d\n", closure->ref_count);
g_closure_unref(closure);
g_value_unset(¶ms[0]);
g_value_unset(¶ms[1]);
g_value_unset(¶ms[2]);
return 0;
}
|