0

I am building a GTK program that does the following: A button gets clicked by the user, it retrieves information from the server, then creates new buttons that the user can click on. I technically have a signal in main, and in that call_back I have multiple signals (for each of the created buttons).

I would like to pass data to this new button, but here it becomes icky. If I create a struct inside my first button I will later crash in the buttons that are generated because the struct is locally defined on the stack, and so it gets deleted.

I cannot create a global variable as each of the created button need different values. I basically would like to pass a struct with multiple fields when my initial button (callback method) gets called, but each of this struct is different.

The only way I can think of is to allocate it on the heap, but it becomes a bit of overhead to know when to free it.

Is there a good way around this please, or am I following wrong design choices for GTK by having a signal handler create a new signal handler please?

Thank you very much.

EDIT:

I am still crashing, and I am very confused why.

This is the code for the main button:

struct buttonData* data = (struct buttonData*) malloc(sizeof(struct buttonData)); data->IP = strdup(newDevice.IP.c_str()); // Added strdup data->port = atoi(newDevice.port.c_str()); g_signal_connect(G_OBJECT(deviceButton), "button_press_event", G_CALLBACK(showDeviceAndConnect), (gpointer) data); 

Code for the button that is generated:

static void showDeviceAndConnect(GtkWidget * deviceButton, gpointer data) { struct buttonData* toConnect = (struct buttonData *) data; fprintf(stderr, "IP: %s, PORT: %d\n", toConnect->IP, toConnect->port); //SIGSEGV } 

I am not sure why. Any help would be very appreciated.

2 Answers 2

2

The reason for the crash is the signature of your callback. "button-press-event" expects the callback with the signature gboolean foo(GtkWidget* , GdkEvent*, gpointer). As you callback has signature of void foo (GtkWidget * , gpointer ) the second parameter which you are getting in the callback function is not gpointer data which used when registering callback but GdkEvent pointer. Thus when you are dereferencing GdkEvent pointer (thinking it as the data you had passed) you are seeing the crash. So to fix this issue change static void showDeviceAndConnect(GtkWidget * deviceButton, gpointer data) to static void showDeviceAndConnect(GtkWidget * deviceButton, GdkEvent *ev, gpointer data).
Alternatively, as you are using only data in showDeviceAndConnect function you can using g_signal_connect_swapped which will pass the data as the first parameter; so if you use g_signal_connect_swapped your function static void showDeviceAndConnect(GtkWidget * deviceButton, gpointer data) can be static void showDeviceAndConnect(gpointer data).
Hope this helps!

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you so so much, it is fixed!
1

The only way I can think of is to allocate it on the heap, but it becomes a bit of overhead to know when to free it.

That is the way to do it. Allocate the structure on the heap and pass a pointer to it as the callback data. Note that even while it does not apply to you since you are dynamically generating those buttons, using global variables is a poor choice as a solution.

4 Comments

Thanks a lot for your help K-ballo. I will use dynamic memory. I just tried using a struct and malloc (I never free it for now), but I get a SIGSEGV with my current code. Do you mind having a quick look into it please? I updated my initial message.
I printed just before g_signal_connect and data prints the right output (from the main button).
@Jary: You know that's not C, its C++, right? You are just referencing to the contents of newDevice's strings, you should be duplicating those contents perhaps with strdup.
Thanks you are right, I completely forgot. I just tried changing the lines to data->IP = strdup(newDevice.IP.c_str()); data->port = atoi(newDevice.port.c_str());, but it still crashes though.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.