为什么我的GTK +信号回调会出现分段错误?
我正在尝试测量GTK标签的大小:
#include static void map_event(GtkWidget *window, gpointer lab) { g_print( "In the callback..\n" ); GtkWidget *label = GTK_WIDGET(lab); g_print( "Everything is ok..\n" ); } static void activate (GtkApplication* app, gpointer user_data) { GtkWidget *window = gtk_application_window_new (app); gtk_window_set_title (GTK_WINDOW (window), "Window1"); gtk_window_set_default_size (GTK_WINDOW (window), 200, 280); GtkWidget *grid = gtk_grid_new (); gtk_container_add (GTK_CONTAINER (window), grid); GtkWidget *label = gtk_label_new("Hello world!"); gtk_grid_attach(GTK_GRID (grid), label, 0,0,1,1); g_signal_connect (window, "map-event", G_CALLBACK(map_event), label); gtk_widget_show_all (window); } int main (int argc, char **argv) { GtkApplication *app = gtk_application_new ( "org.gtk.example", G_APPLICATION_FLAGS_NONE ); g_signal_connect( app, "activate", G_CALLBACK(activate), NULL); int status = g_application_run(G_APPLICATION(app), argc, argv); g_object_unref (app); return status; }
这给出了输出:
In the callback.. Segmentation fault (core dumped)
如果我注释掉这条线:
GtkWidget *label = GTK_WIDGET(lab);
没有分段错误,标签显示,输出为:
In the callback.. Everything is ok..
我在这里想念的是什么?
map-event
具有以下签名,因此您缺少GdkEvent*
参数:
gboolean user_function (GtkWidget *widget, GdkEvent *event, gpointer user_data)
不幸的是,GTK +是用C语言编写的,所以它缺少类型安全的回调函数,所以很容易犯这样的错误。
您不尊重信号签名。 每个信号都与您必须遵守的预定义函数原型相关联,否则您将只读取垃圾。 在这里,您只是想出了回调签名,因此事情将无法按预期工作。
信号就像一个美味的水果送货服务。 通过连接到该信号,您签署了一份订阅水果交付服务的合同。 只有在水果成熟时才会送出水果。 送货员将:
- 来到你家门口
- 放一些水果盒给你
- 敲门
- 回到它的卡车
合同还规定:
- 方框#1将包含香蕉
- 方框#2将包含苹果
- 方框#3将包含橙子
那些盒子就像你回调的参数。 map-event有3个参数,因此有3个参数。
有一天,你听到敲门声。 你打开门,看到盒子,打开盒子#2,生气地说“该死,我说我想要橘子!”。 问题是你要混合苹果和橙子:按照合同,橘子在#3盒子里,你在盒子#2中寻找它们。
因此,请查看要连接的每个信号的文档。 这是编写正确回调的唯一方法。 在这里你忘记了一个输入参数以及返回值。 在map-event
的情况下,当您前往卡车说明您是想要继续还是停止交付时,可以看到该返回值。