C-在回调函数中访问GTK小部件的结构时,如何避免segfault



我有一个回调函数,需要访问多个GTK小部件。为了实现这一目标,我试图将指针发送到结构中包装的相关GTK小部件作为回调函数的参数(而不是使用全局变量来启用访问)。为了以一种很好的方式构造数据,我将指针结构用于指针到GTK小部件的结构。

我的问题是,在回调函数中尝试阅读或写入GTK小部件时,我会遇到细分故障。我该如何避免这种情况?当我刚刚开始学习C和GTK时,我的方法可能完全不合适,因此我也很感激从回调函数访问多个GTK小部件的更一般问题的指示。

试图解决问题时,我设法将提出问题的代码归结为以下内容。在更改SpinButton的值时,它会出现。如果让widget_change_value中的最后一行执行。

/* Compile with gcc foo.c `pkg-config --cflags --libs gtk+-2.0` */
#include <gtk/gtk.h> /* Get e.g. via sudo apt-get install libgtk2.0-dev */
typedef struct {
    GtkWidget *widget;
} s_input;
typedef struct {
    s_input *input;
} s_data;
void widget_change_value(s_data *data) {
    /* Segfault when trying to read from data  */
    int number = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(data->input->widget));
    /* /* Segfault when trying to write to data */ */
    /* gtk_spin_button_set_value(GTK_SPIN_BUTTON(data->input->widget), (gdouble) 2.0); */
}
int main(int argc, char *argv[])
{
    GtkWidget *window;
    s_input input;
    s_data data = { &input };
    gtk_init(&argc, &argv);
    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    input.widget = gtk_spin_button_new_with_range(0, 3, 1);
    gtk_container_add(GTK_CONTAINER(window), input.widget);
    g_signal_connect(GTK_OBJECT(input.widget), "value_changed", GTK_SIGNAL_FUNC(widget_change_value), (gpointer *) &data);
    gtk_widget_show_all(window);
    gtk_main();
    return 0;
}

您的崩溃是因为您的回调函数的原型都是错误的。

您有:

void widget_change_value(s_data *data);

但是看文档,value-changed信号处理程序回调称为:

void user_function(GtkSpinButton *spinbutton, gpointer user_data);

您需要添加缺少的窗口小部件指针参数。

也:

  1. 您的回调应为 static,因为它在c文件中是非常本地的。
  2. 您不需要将事情扔给gpointer
  3. (gpointer *)的铸件是双重错误的,因为您要传递一个指针(&data),该指针要转换为gpointer将其转换为"指针到gpointer"。星号是错误的。但是,正如我上面说的那样,整个演员阵容都是毫无意义的,应该被删除。
  4. 考虑移植到最近的GTK 版本,您正在使用一些过时的东西(GTK_OBJECT()而不是G_OBJECT()GTK_SIGNAL_FUNC()而不是G_CALLBACK())。

最新更新