GTK+ g_pointer_connect错误地传递数据



使用 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);

这段代码中的g_print输出"777"。但是,当函数被调用时

static void funct(gpointer data) {
  g_print(std::to_string(*(guint*)data).c_str());
}

g_prints输出一些垃圾,例如:"81382720">

谁能帮我解决这个问题?

您正在传递指向局部变量 ( x ( 的指针,并在堆栈上分配一个局部变量。要使它在该函数的作用域之外保持活动状态,请改为在堆上分配它(或者可以选择使用静态或全局变量(。

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

当您不再需要指针时,不要忘记调用g_free来释放该指针,以避免内存泄漏。

编辑:

我错过了您的回调签名是错误的这一事实,因为它不尊重销毁信号之一。这是一个错误,必须修复。感谢el.pescado指出这一点。

对其他帖子的评论也是有效的,但不影响正确性:

  • GUINT_TO_POINTER/GPOINTER_TO_UINT可用于这种简单情况以避免动态分配
  • 你打电话给g_print是不必要的复杂

首先,默认情况下,信号处理程序接收指向接收信号作为第一个参数的对象的指针,将用户数据作为最后一个参数。因此,信号处理程序应具有以下签名:

static void funct(GtkWidget *object, gpointer data) {
  /* ... */
}

其次,x 是一个本地值,因此在调用回调时它可能(尽管不一定(超出范围。要修复它,你可以通过在堆上分配它来延长它的生命周期(g_newnewmalloc(或让它成为全局/静态的。或者,由于uint适合指针,因此您可以使用宏GUINT_TO_POINTER/GPOINTER_TO_UINT直接在指针中存储/检索x

最后,g_print函数提供格式化输出,如printf - 而不是创建临时std::string并从中提取字符指针:

g_print(std::to_string(*(guint*)p).c_str());

您可以简单地使用%u格式说明符来打印guint

g_print("%u", *p);

总结一下:

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

我怀疑变量 x 已经超出了范围,并且在调用窗口的"销毁"信号时调用回调时被销毁。因此,指针在取消引用时不再有效。

如果只想存储整数值,请使用 GINT_TO_POINTER() 来存储该值:

guint x = 777;
g_signal_connect(G_OBJECT(dialogWindow), "destroy",
    G_CALLBACK(funct), GINT_TO_POINTER(x));

GPOINTER_TO_INT()检索它:

static void funct(gpointer data) {
    guint x = GPOINTER_TO_INT(data);
}

最新更新