在回调函数中访问GTK小部件结构时如何避免段错误?

时间:2012-10-31 11:51:04

标签: c gtk

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

我的问题是在尝试读取或写入回调函数中的GTK小部件时出现分段错误。我怎么能避免这个?由于我刚刚开始学习C和GTK,我的方法可能完全不合适,所以我也很感激指出从回调函数访问几个GTK小部件的更一般的问题。

在尝试修复问题时,我设法将代码问题归结为以下问题。更改旋钮的值时会出现段错误。如果让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;
}

1 个答案:

答案 0 :(得分:3)

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

你有:

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()