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

GTK4 C语言回调函数无法通过指针修改Entry组件求助

GTK4下拉框回调同步输入框问题的解决方案

问题根源

你的代码存在两个核心错误:

  1. 回调函数签名不匹配:notify::selected-item信号的标准回调原型为:
    void callback(GObject *object, GParamSpec *pspec, gpointer user_data);
    
    你定义的回调仅接收两个参数,导致data实际接收到的是GParamSpec*而非传递的数组,参数完全错位。
  2. 用户数据是局部栈变量:entryAndBuffer是activateApp函数内的局部数组,函数执行完毕后栈内存被释放,回调触发时访问该内存属于未定义行为。

修复方案1:简化逻辑,仅传递输入框指针

无需单独传递Buffer,直接通过输入框获取并修改现有Buffer内容,代码更简洁高效:

修改回调函数签名与实现

static void baudrateDropdownSelectCallback(GObject *dropdown, GParamSpec *pspec, gpointer user_data);

static void baudrateDropdownSelectCallback(GObject *dropdown, GParamSpec *pspec, gpointer user_data) {
    GtkWidget *baudrateEntry = GTK_WIDGET(user_data);
    GtkStringObject *selectedItem = GTK_STRING_OBJECT(gtk_drop_down_get_selected_item(GTK_DROP_DOWN(dropdown)));
    const char *selectedStr = gtk_string_object_get_string(selectedItem);

    // 获取输入框现有Buffer,直接修改内容
    GtkEntryBuffer *buffer = gtk_entry_get_buffer(GTK_ENTRY(baudrateEntry));
    gtk_entry_buffer_set_text(buffer, selectedStr, -1);
}

修改信号连接代码

在activateApp函数中,直接传递baudrateEntry作为用户数据:

g_signal_connect(baudrateDropdown, "notify::selected-item", G_CALLBACK(baudrateDropdownSelectCallback), baudrateEntry);

修复方案2:传递多数据(动态分配结构体)

如果确实需要传递多个组件指针,使用动态分配的结构体避免栈内存回收问题:

定义数据结构体

typedef struct {
    GtkWidget *entry;
    GtkEntryBuffer *buffer;
} CallbackData;

分配数据并连接信号

在activateApp函数中:

CallbackData *data = g_malloc(sizeof(CallbackData));
data->entry = baudrateEntry;
data->buffer = baudrateEntryBuffer;
g_signal_connect(baudrateDropdown, "notify::selected-item", G_CALLBACK(baudrateDropdownSelectCallback), data);

// 可选:窗口销毁时释放结构体
g_signal_connect(win, "destroy", G_CALLBACK(winDestroyCallback), data);

回调函数实现与内存清理

static void baudrateDropdownSelectCallback(GObject *dropdown, GParamSpec *pspec, gpointer user_data) {
    CallbackData *data = (CallbackData*)user_data;
    GtkStringObject *selectedItem = GTK_STRING_OBJECT(gtk_drop_down_get_selected_item(GTK_DROP_DOWN(dropdown)));
    const char *selectedStr = gtk_string_object_get_string(selectedItem);

    // 替换输入框Buffer
    GtkEntryBuffer *newBuffer = gtk_entry_buffer_new(selectedStr, -1);
    gtk_entry_set_buffer(GTK_ENTRY(data->entry), newBuffer);
    
    // 释放旧Buffer引用
    g_object_unref(data->buffer);
    data->buffer = newBuffer;
}

// 窗口销毁回调:释放结构体内存
static void winDestroyCallback(GtkWidget *win, gpointer user_data) {
    CallbackData *data = (CallbackData*)user_data;
    g_free(data);
}

额外优化建议

  • 优先使用gtk_entry_buffer_set_text修改现有Buffer内容,避免频繁新建Buffer造成的内存开销。
  • 类型转换时使用GTK官方类型宏(如GTK_DROP_DOWN、GTK_ENTRY),确保类型安全。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 22:16:33