I have a callback function that needs to access several GTK widgets. To enable this I am trying to send pointers to the relevant GTK widgets packaged in a structure as an argument to the callback function (instead of using global variables to enable access). To structure the data in a nice way I use a structure of pointers to structures of pointers to GTK widgets.
My problem is that I get segmentation fault when trying to read from or write to the GTK widgets in the callback function. How can I avoid this? As I just started learning C and GTK my approach may be inappropriate altogether, so I would also appreciate pointers on the more general of problem of accessing several GTK widgets from callback functions.
In trying to fix the problem I have managed to boil down the code that presents the problem to the following. It segfaults when changing the value of the spinbutton. It also segfault if one lets the last line in widget_change_value execute instead.
/* 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;
}
Your crash is because your callback function’s prototype is all wrong.
You have:
but looking at the docs, the
value-changedsignal handler callback is declared as:You need to add the missing widget pointer argument.
Also:
static, since it’s very local to the C file it’s in.gpointer.(gpointer *)is doubly wrong, since you’re passing a pointer (&data) which you want to convert togpointer, not to “pointer togpointer“. The asterisk is wrong. But, as I said above, the entire cast is pointless and should be removed.GTK_OBJECT()instead ofG_OBJECT(),GTK_SIGNAL_FUNC()instead ofG_CALLBACK(), for instance).