GTK passing structure to callback function in C

对着背影说爱祢 提交于 2021-01-28 05:01:04

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!