Получение предупреждения GLib при передаче struct as arg в G_CALLBACK - PullRequest
0 голосов
/ 25 февраля 2019

Я пытаюсь передать указатель на struct в качестве аргумента функции обратного вызова, но я получаю эту ошибку

(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;

Ссылка на программу здесь

Код работал нормально, когда я передавал app в качестве данных функции g_signal_connect_swapped.Но при передаче той же переменной, что и элемент структуры, я получаю это предупреждение.

1 Ответ

0 голосов
/ 27 февраля 2019

Александр Дмитриев правильно понял.Вы пытаетесь использовать arg в second_win, но поскольку arg является структурой, размещенной в стеке, как только вы возвращаетесь из этой функции, она перестает существовать.Есть два решения, чтобы arg прожить достаточно долго:

  • выделить его в куче (с malloc или g_malloc / g_new / g_new0)
  • выделите его в стеке в функции, из которой вы вернетесь, только когда arg больше не используется

Вот патч, который использует второе решение.Вы можете сохранить его в 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
...