使用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”
任何人都可以帮我吗?
答案 0 :(得分: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
的来电是不必要的复杂答案 1 :(得分:2)
首先,信号处理程序默认接收指向接收信号作为第一个参数的对象,并将用户数据作为最后一个参数。因此,您的信号处理程序应具有以下signature:
static void funct(GtkWidget *object, gpointer data) {
/* ... */
}
其次,x
是一个本地值,因此在调用回调时它可能(但不一定)超出范围。要修复它,您可以通过在堆上分配它(g_new
,new
,malloc
)或使其成为全局/静态来延长其生命周期。或者,由于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));
}
答案 2 :(得分:1)
我怀疑变量x已经超出范围并且在窗口“#s;" destroy"信号被叫。因此,当取消引用时,指针不再有效。
答案 3 :(得分: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);
}