GTK + g_pointer_connect错误地传递数据

问题描述 投票:1回答:4

使用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”

谁能帮我这个?

c++ gtk
4个回答
2
投票

您正在传递指向局部变量(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的调用是不必要的复杂

2
投票

首先,信号处理程序默认接收指向接收信号作为第一个参数的对象,并将用户数据作为最后一个参数接收。所以,你的信号处理程序应该有以下signature

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

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

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

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

1
投票

我怀疑变量x已经超出范围并且在调用窗口的“destroy”信号时调用回调时被销毁。因此,当解除引用时,指针不再有效。


0
投票

如果您只想存储整数值,请使用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);
}
© www.soinside.com 2019 - 2024. All rights reserved.