Reputation: 85
I have a problem with passing my data to the function when using g_signal_connect().
guint x = 777;
gpointer ptr = &x;
g_print(std::to_string(*(guint*)p).c_str());
g_signal_connect(G_OBJECT(dialogWindow), "destroy",
G_CALLBACK(funct), ptr);
The g_print in this piece of code outputs "777". However when the funct is called
static void funct(gpointer data) {
g_print(std::to_string(*(guint*)data).c_str());
}
the g_prints outputs some garbage like: "81382720"
Can anyone help me with this?
Upvotes: 2
Views: 531
Reputation: 11454
You're passing a pointer to a local variable (x
), and a local variable is allocated on the stack. To keep it alive outside of the scope of that function, allocate it on the heap instead (or optionally use a static or global variable).
guint *ptr = g_malloc(sizeof(guint));
*ptr = 777;
g_print(std::to_string(*ptr).c_str());
g_signal_connect(G_OBJECT(dialogWindow), "destroy",
G_CALLBACK(funct), ptr);
Don't forget to call g_free
to free that pointer when you don't need it anymore to avoid a memory leak.
EDIT:
I missed the fact that the signature of your callback is wrong as it doesn't respect the one of the destroy signal. This is a bug and must be fixed. Thanks to el.pescado for pointing that out.
Remarks on the other posts are valid too, but don't affect correctness:
GUINT_TO_POINTER
/GPOINTER_TO_UINT
can be used for that simple case to avoid dynamic allocationg_print
is unnecessary complicatedUpvotes: 3
Reputation: 19204
First, signal handlers receive by default pointer to object that received signal as first argument, and user data as last argument. So, your signal handler should have the following signature:
static void funct(GtkWidget *object, gpointer data) {
/* ... */
}
Second, x
is a local value, so it might (though not necessarily) be out of scope by the time callback is called. To fix it you could either extend its lifetime by allocating it on heap (g_new
, new
, malloc
) or making it global/static. Alternatively, since an uint
fits in pointer, you could use macros GUINT_TO_POINTER
/GPOINTER_TO_UINT
to store/retrieve x
directly in pointer.
Last, g_print
function provides formatted output like printf
- instead of creating temporary std::string
and extracting char pointer form it:
g_print(std::to_string(*(guint*)p).c_str());
You could simply use %u
format specifier to print guint
:
g_print("%u", *p);
To sum up:
guint x = 777;
g_print("%u", x);
g_signal_connect(G_OBJECT(dialogWindow), "destroy",
G_CALLBACK(funct), GUINT_TO_POINTER(x));
// ...
static void funct(GtkWidget *object, gpointer data) {
g_print("%u", GPOINTER_TO_UINT(data));
}
Upvotes: 2
Reputation: 6208
If you just want to store an integer value, use GINT_TO_POINTER()
to store the value :
guint x = 777;
g_signal_connect(G_OBJECT(dialogWindow), "destroy",
G_CALLBACK(funct), GINT_TO_POINTER(x));
and GPOINTER_TO_INT()
to retrieve it:
static void funct(gpointer data) {
guint x = GPOINTER_TO_INT(data);
}
Upvotes: 1
Reputation: 388
I'm suspecting that variable x is already out of scope and destroyed when callback get called when the window's "destroy" signal get called. Thus the pointer is not valid anymore when it is dereferenced.
Upvotes: 1