Reputation: 1521
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.
Upvotes: 0
Views: 980
Reputation: 11395
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!
Upvotes: 2
Reputation: 81349
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.
Upvotes: 1