1

I am trying to measure the size of a GTK label:

#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?

liberforce
  • 11,189
  • 37
  • 48
Håkon Hægland
  • 39,012
  • 21
  • 81
  • 174
  • Use the debugger... – Basile Starynkevitch Jan 11 '18 at 05:24
  • @BasileStarynkevitch The debugger says `Thread 1 "label_test" received signal SIGSEGV, Segmentation fault. 0x00007ffff6f07de2 in g_type_check_instance_cast () from /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0` – Håkon Hægland Jan 11 '18 at 05:38
  • Don't comment your question, but do edit it. Learn to [use the `gdb` debugger](https://sourceware.org/gdb/current/onlinedocs/gdb/). It has extensive facilities to query the call stack (`backtrace` command) and local variables. Use them to understand what is really going on. – Basile Starynkevitch Jan 11 '18 at 05:40
  • You could add some asserts (e.g. using `g_assert` or `assert`), i.e. check that `GTK_IS_LABEL(label)`...) – Basile Starynkevitch Jan 11 '18 at 05:42
  • Also, explain in your question why do you care about the size of the label. Containers like grids deal with that very well. What is your overall goal? Why don't you use layout facilities? – Basile Starynkevitch Jan 11 '18 at 05:46

2 Answers2

4

map-event has following signature, so you are missing GdkEvent* argument:

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.

4

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
  • box #2 will contain apples
  • box #3 will contain oranges

Those boxes are like the arguments of your callback. The map-event takes 3 arguments, thus the 3 boxes.

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!". 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.

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.

liberforce
  • 11,189
  • 37
  • 48
  • Thanks, great explanation! I was looking at some tutorial examples and mistakenly thought all callbacks would look the same (take the same arguments). – Håkon Hægland Jan 11 '18 at 09:46
  • 2
    You're not the only one. That error is in the top 3 programming errors newcommers to GTK+ do. – liberforce Jan 11 '18 at 09:55