使用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
的调用是不必要的复杂首先,信号处理程序默认接收指向接收信号作为第一个参数的对象,并将用户数据作为最后一个参数接收。所以,你的信号处理程序应该有以下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));
}
我怀疑变量x已经超出范围并且在调用窗口的“destroy”信号时调用回调时被销毁。因此,当解除引用时,指针不再有效。
如果您只想存储整数值,请使用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);
}