在将结构作为 arg 传递给 G_CALLBACK 时获取 GLib 警告

Getting GLib warning on passing struct as arg to G_CALLBACK

我试图将一个指向结构的指针作为参数传递给回调函数,但我收到了这个错误

(gtk:11156): GLib-GObject-WARNING **: 22:34:21.308: invalid cast from 'GtkEntry' to 'GtkApplication'

(gtk:11156): Gtk-CRITICAL **: 22:34:21.308: gtk_application_window_new: assertion 'GTK_IS_APPLICATION (application)' failed

执行这段代码时

Appnfile *argptr = (Appnfile*)data;
GtkWidget *window2 = gtk_application_window_new(GTK_APPLICATION(argptr->app1));  //this line has the error

回调函数的原型是

static void second_win(GtkEntry *entry, gpointer data);

结构声明和g_signal_connect行是

Appnfile arg;
arg.app1=app;
arg.buff=buffer;
g_signal_connect(name, "activate",G_CALLBACK(second_win),&arg);

结构的定义是

typedef struct {
    GApplication *app1;
    GtkEntryBuffer *buff;
} Appnfile;

Link给的程序是 here

当我在 g_signal_connect_swapped 函数上将应用程序作为数据传递时,代码运行良好。但是在传递与结构元素相同的变量时,我收到了这个警告。

亚历山大·德米特里耶夫说得对。您正在尝试在 second_win 中使用 arg,但由于 arg 是在堆栈上分配的结构,一旦您从该函数 return ,它就不再存在.要让 arg 活得足够长,有两种解决方案:

  • 在堆上分配它(使用malloc,或g_malloc/g_new/g_new0
  • 仅在 arg 不再使用时 return 在函数中将其分配到堆栈上

这是使用第二种解决方案的补丁。您可以将其保存在 arg.patch 中并应用 git am arg.patch:

From 6c0679485cde31c55c58aa5f54f0a60d4c874d71 Mon Sep 17 00:00:00 2001
From: Luis Menina <liberforce@freeside.fr>
Date: Wed, 27 Feb 2019 10:41:58 +0100
Subject: [PATCH] Create argument list where it will live long enough to be
 accessed

Declaring it on the stack inside a callback will make it be destroyed
when you exit the callback. By declaring it in the stack, in the main
you are sure that the structure has the same lifespan as your
application.
---
 prog_c/gtk_pr_a.c | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/prog_c/gtk_pr_a.c b/prog_c/gtk_pr_a.c
index fb3b5a2..d11ba7d 100644
--- a/prog_c/gtk_pr_a.c
+++ b/prog_c/gtk_pr_a.c
@@ -80,6 +80,7 @@ static void first_win(GApplication *app, gpointer data){
     GObject *window, *name;
     GError *error =NULL;
     GtkEntryBuffer *buffer;
+    Appnfile *arg = data;

     builder= gtk_builder_new();
     if(gtk_builder_add_from_file( builder, "pr1.ui",&error)==0){
@@ -97,10 +98,9 @@ static void first_win(GApplication *app, gpointer data){
     gtk_widget_show_all(GTK_WIDGET(window));
     g_signal_connect( name, "activate", G_CALLBACK(search_user),buffer);

-    Appnfile arg;
-    arg.app1=app;
-    arg.buff=buffer;
-    g_signal_connect(name, "activate",G_CALLBACK(second_win),&arg);
+    arg->app1=app;
+    arg->buff=buffer;
+    g_signal_connect(name, "activate",G_CALLBACK(second_win), arg);
     g_signal_connect_swapped( name, "activate", G_CALLBACK(gtk_window_close),window);
     g_object_unref(window);
 }
@@ -117,7 +117,10 @@ static void first_win(GApplication *app, gpointer data){
 int main(int argc, char *argv[]){
     GtkApplication *app = gtk_application_new("org.my.app",
                         G_APPLICATION_FLAGS_NONE);
-    g_signal_connect(app, "activate", G_CALLBACK(first_win),NULL);
+    Appnfile arg;
+    memset(&arg, 0, sizeof(arg));
+
+    g_signal_connect(app, "activate", G_CALLBACK(first_win), &arg);
     //g_signal_connect(app, "2win",G_CALLBACK(second_win),NULL);
     int status =g_application_run(G_APPLICATION(app),argc, argv);
     g_object_unref(app);
-- 
2.17.1