GTK将结构传递给C中的回调函数

时间:2016-04-16 21:16:10

标签: c callback gtk signals

在GTK中还是新手,现在正在努力处理事件驱动的编程并陷入奇怪的境地:将标量项发送到回调函数没有问题,但后来发送结构到它,仍然收到错误不知道出了什么问题。

示例“存根”代码是:

#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);
}

现在出现如下错误:

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;

任何帮助将不胜感激!

1 个答案:

答案 0 :(得分:4)

这里有几个C错误。 GTK允许您在某些功能上传递gpointer user_datagpointer只是void *(即指向某事的指针)。如果要传递结构,则需要结构的地址,而不是结构本身。这被称为传递地址,而不是传递值

所以,而不是:

g_signal_connect (entryMainValue, "activate", G_CALLBACK (messageup), d);

写:

g_signal_connect (entryMainValue, "activate", G_CALLBACK (messageup), &d);

然后,当您进行回调时,您收到的user_data参数是指向某事的指针。您需要将其转换为指向结构的指针。

所以而不是:

void messageup(GtkWidget *entryMainValue, gpointer user_data)
{
    struct data *d = (struct data*) user_data;
    g_print("Hello World!\n%s\n", user_data.message);
}

您需要使用正确类型的指针(d,而不是user_data)访问消息字段,并使用->运算符作为您'通过指针访问结构:

void messageup(GtkWidget *entryMainValue, gpointer user_data)
{
    struct data *d = user_data;
    g_print("Hello World!\n%s\n", d->message);
}

你似乎对指针感到困惑,所以看看这个好video about C pointers

另一个错误是连接到delete-event退出。此事件是您希望捕获用户单击窗口的退出十字或使用Alt-F4退出的事实,并且您希望在此时执行某些操作(显示确认弹出窗口,保存一些数据)。所以没有必要在那里连接,将发生破坏(使用destroy信号)。

所以改为连接到delete-event信号,连接到destroy信号,并响应此信号,退出GTK +主循环:

g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);