问题
Still new in GTK, now trying to work on event-driven programming and stuck in weird situation: there is no problem to send scalar items to callback function, but then it comes to sending struct to it, still receiving the error with no idea what's wrong.
Sample "stub" code is:
#include <gtk/gtk.h>
#include <stdlib.h>
void messageup();
void exiting();
struct data{
char *message;
GtkWidget *window;
};
int main (int argc, char *argv[])
{
GtkBuilder *builder;
GtkWidget *window;
GtkWidget *entryMainValue;
struct data d;
gtk_init (&argc, &argv);
builder = gtk_builder_new ();
gtk_builder_add_from_file (builder, "samplemain.ui", NULL);
window = GTK_WIDGET (gtk_builder_get_object (builder, "applicationwindow1"));
entryMainValue = GTK_WIDGET (gtk_builder_get_object (builder, "entryMainValue"));
g_signal_connect (window, "delete_event", G_CALLBACK (exiting), NULL);
d.message = "message\n";
d.window = window;
g_signal_connect (entryMainValue, "activate", G_CALLBACK (messageup), d);
g_object_unref (G_OBJECT (builder));
gtk_widget_show (window);
gtk_main ();
return 0;
}
void messageup(GtkWidget *entryMainValue, gpointer user_data){
struct data *d = (struct data*) user_data;
g_print("Hello World!\n%s\n", user_data.message);
}
void exiting()
{
exit(0);
}
Now having the error looking like this:
gtkbldprj.c: In function ‘main’:
gtkbldprj.c:29:3: error: incompatible type for argument 4 of ‘g_signal_connect_data’
g_signal_connect (entryMainValue, "activate", G_CALLBACK (messageup), d);
^
In file included from /usr/include/glib-2.0/gobject/gobject.h:28:0,
from /usr/include/glib-2.0/gobject/gbinding.h:29,
from /usr/include/glib-2.0/glib-object.h:23,
from /usr/include/glib-2.0/gio/gioenums.h:28,
from /usr/include/glib-2.0/gio/giotypes.h:28,
from /usr/include/glib-2.0/gio/gio.h:26,
from /usr/include/gtk-3.0/gdk/gdkapplaunchcontext.h:28,
from /usr/include/gtk-3.0/gdk/gdk.h:32,
from /usr/include/gtk-3.0/gtk/gtk.h:30,
from gtkbldprj.c:1:
/usr/include/glib-2.0/gobject/gsignal.h:388:9: note: expected ‘gpointer’ but argument is of type ‘struct data’
gulong g_signal_connect_data (gpointer instance,
^
gtkbldprj.c: In function ‘messageup’:
gtkbldprj.c:42:41: error: request for member ‘message’ in something not a structure or union
g_print("Hello World!\n%s\n", user_data.message);
^
gtkbldprj.c:39:15: warning: unused variable ‘d’ [-Wunused-variable]
struct data *d = (struct data*) user_data;
Any help will be appreciated!
回答1:
There are several C errors here.
GTK allows you on some functions to pass a gpointer user_data
. A gpointer
is just a void *
(ie. a pointer to something). If you want to pass a structure, you need the address of the structure, not the structure itself. That is called passing by address, as opposed to passing by value.
So, instead of:
g_signal_connect (entryMainValue, "activate", G_CALLBACK (messageup), d);
write:
g_signal_connect (entryMainValue, "activate", G_CALLBACK (messageup), &d);
Then, when you're in the callback, the user_data
parameter you receive is a pointer to something. You need to transform it into a pointer to your structure.
So instead of:
void messageup(GtkWidget *entryMainValue, gpointer user_data)
{
struct data *d = (struct data*) user_data;
g_print("Hello World!\n%s\n", user_data.message);
}
You need to access the message field using a pointer of the right type (d
, not user_data
), and use the ->
operator as you're accessing the structure through a pointer:
void messageup(GtkWidget *entryMainValue, gpointer user_data)
{
struct data *d = user_data;
g_print("Hello World!\n%s\n", d->message);
}
You seem confused about pointers, so give a look at this nice video about C pointers.
Another error is connecting to the delete-event
to exit. This event is when you want to catch the fact that the user clicked on the exit cross of the window, or used Alt-F4 to exit, and you want to do something at that moment (show a confirmation popup, save some data). So there's no need to connect there, the destruction will happen (that uses the destroy
signal).
So instead of connecting to the delete-event
signal, connect to the destroy
signal, and in response to this signal, exit the GTK+ main loop:
g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
来源:https://stackoverflow.com/questions/36669855/gtk-passing-structure-to-callback-function-in-c