为什么我的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的情况下,当您前往卡车说明您是想要继续还是停止交付时,可以看到该返回值。