GTK+ g_pointer_connect passing data incorrectly

|▌冷眼眸甩不掉的悲伤 提交于 2019-12-23 03:28:20

问题


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?


回答1:


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 allocation
  • your call to g_print is unnecessary complicated



回答2:


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));
}



回答3:


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.




回答4:


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);
}


来源:https://stackoverflow.com/questions/48522369/gtk-g-pointer-connect-passing-data-incorrectly

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!