You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GTK+中g_signal_connect传递数据异常,请求技术帮助

问题原因与解决方案

这问题我之前做GTK项目时也踩过一模一样的坑!核心问题出在你传递的x是局部栈变量:

你定义的guint x = 777;是某个函数内的局部变量,它存储在栈内存中。当包含这段代码的函数执行完毕后,栈帧会被销毁,这块内存会被系统回收或后续函数调用覆盖。
你当时用g_print能输出777,是因为那时候函数还没执行完,x的内存还处于有效状态;但等到destroy回调触发时,ptr指向的已经是无效的栈内存了,读出来自然是随机的垃圾值。

下面给你三种可行的解决方法,按需选择:

方法1:动态分配内存(推荐,无生命周期冲突)

用GLib的g_new()在堆上分配内存,这样内存不会随函数结束销毁,记得在回调里释放避免泄漏:

// 堆上分配内存并赋值
guint *x = g_new(guint, 1);
*x = 777;

// 传递堆指针给回调
g_signal_connect(G_OBJECT(dialogWindow), "destroy", G_CALLBACK(funct), x);

// 回调函数
static void funct(gpointer data) {
    guint *val = (guint*)data;
    g_print("%u\n", *val);
    g_free(val); // 必须释放堆内存,防止泄漏
}

方法2:使用静态变量

把x声明为static,这样它会存储在全局数据区,生命周期和程序一致,不会随函数结束销毁:

// 静态变量,全局数据区存储
static guint x = 777;

// 传递静态变量的地址
g_signal_connect(G_OBJECT(dialogWindow), "destroy", G_CALLBACK(funct), &x);

// 回调函数
static void funct(gpointer data) {
    guint val = *(guint*)data;
    g_print("%u\n", val);
    // 静态变量不需要手动释放
}

⚠️ 注意:如果这段代码会被多次执行(比如循环、多次调用的函数),静态变量的值会被覆盖,不适合这种场景。

方法3:绑定到GObject的自定义数据(GTK风格)

利用GTK对象的g_object_set_data()机制,把数据绑定到dialogWindow上,和对象生命周期绑定:

guint x = 777;
// 把数值转成gpointer存储到对象上
g_object_set_data(G_OBJECT(dialogWindow), "my-dialog-data", GUINT_TO_POINTER(x));

// 传递窗口对象本身给回调
g_signal_connect(G_OBJECT(dialogWindow), "destroy", G_CALLBACK(funct), dialogWindow);

// 回调函数
static void funct(GtkWidget *widget, gpointer data) {
    // 从对象上取出数据并转成guint
    guint val = GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(widget), "my-dialog-data"));
    g_print("%u\n", val);
}

这种方法不需要手动管理内存,对象销毁时相关数据会自动清理,非常贴合GTK项目的开发习惯。

内容的提问来源于stack exchange,提问作者Cyanide

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 06:31:46