简体   繁体   English

为什么我的GTK +信号回调出现分段错误?

[英]Why do I get a segmentation fault in my GTK+ signal callback?

I am trying to measure the size of a GTK label: 我正在尝试测量GTK标签的大小:

#include <gtk/gtk.h>

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;
}

This gives output: 这给出了输出:

In the callback..
Segmentation fault (core dumped)

If I comment out the line: 如果我将这一行注释掉:

GtkWidget *label = GTK_WIDGET(lab);

there is no segmentation fault, the label shows up and the output is: 没有分段错误,标签显示出来,输出为:

In the callback..
Everything is ok..

What am I missing here? 我在这里想念什么?

map-event has following signature, so you are missing GdkEvent* argument: map-event具有以下签名,因此您缺少GdkEvent*参数:

gboolean
user_function (GtkWidget *widget,
               GdkEvent  *event,
               gpointer   user_data)

Unfortunately, GTK+ is written in C, so it lacks type-safe callback functions, so it's easy to make mistakes such as this. 不幸的是,GTK +是用C编写的,因此缺少类型安全的回调函数,因此很容易犯这样的错误。

You don't respect the signal signature. 您不尊重信号签名。 Each signal is associated with a pre-defined function prototype you must respect, otherwise you'll just read garbage. 每个信号都与您必须遵守的预定义函数原型相关联,否则您将只阅读垃圾。 Here you just made up out of your mind the callback signature so things won't work as expected. 在这里,您只是想出了回调签名,所以事情将无法按预期进行。

The signal is like a delicious fruit delivery service. 信号就像美味的水果送货服务。 By connecting to that signal, you signed a contract that subscribe you to the fruit delivery service. 通过连接到该信号,您签署了一份合同,使您订阅水果交付服务。 Fruit will be delivered only when the fruit is ripe. 水果只有在成熟时才能交付。 The delivery man will: 送货员将:

  • come in front of your home 来你家门口
  • drop some fruit boxes for you 给你放一些水果盒
  • knock at your door 敲门
  • go back to its truck 回到卡车上

The contract also specifies that: 合同还规定:

  • box #1 will contain bananas 盒子#1将包含香蕉
  • box #2 will contain apples 盒子#2将包含苹果
  • box #3 will contain oranges 框#3将包含橘子

Those boxes are like the arguments of your callback. 这些框就像您的回调的参数。 The map-event takes 3 arguments, thus the 3 boxes. 映射事件需要3个参数,因此需要3个框。

One day, you hear knocking at the door. 有一天,你听到敲门声。 You open the door, see the boxes, open box #2 and get annoyed saying "damn, I said I wanted oranges!". 您打开门,看到盒子,打开2号盒子,然后生气地说:“该死,我说我要桔子!”。 The thing is that you're mixing apples and oranges: by contract, oranges are in box #3 and you're looking for them in box #2. 事实是,您正在混合苹果和橙子:根据合同,橙子在3号框中,而您正在2号框中寻找它们。

So give a look at the documentation of each signal you want to connect to. 因此,请查看您要连接的每个信号的文档。 That's the only way to write the right callback. 这是编写正确的回调的唯一方法。 Here you forgot one input parameter as well as the return value. 在这里,您忘记了一个输入参数以及返回值。 In the case of map-event , that return value can be seen as you going to the truck to say if you want to continue or stop the deliveries. map-event的情况下,返回值可以在您去卡车上说要继续还是停止交付时看到。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM