2016-04-16 5 views
1

Noch neu in GTK, jetzt versucht, an ereignisgesteuerten Programmierung arbeiten und stecken in seltsame Situation: Es gibt kein Problem, skalare Elemente an Callback-Funktion senden, aber dann kommt es zu senden struct dazu, immer noch den Fehler ohne Ahnung, was los ist.GTK übergeben Struktur an Callback-Funktion in C

Sample "Stub" Code ist:

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

nun den Fehler wie folgt aussehen mit:

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; 

Jede Hilfe wird geschätzt!

+0

Versuchen Sie mit einem Zeiger anstelle von struct? – Boiethios

+2

Übergeben Sie die Adresse von 'd', d. H.' & D', anstelle von 'd'. – user4815162342

+0

Guter Punkt! Jetzt, wie man die Struktur auf Rückruffunktionsseite richtig analysiert? :) – LifeOnNet

Antwort

3

Hier sind mehrere C Fehler. GTK ermöglicht es Ihnen, bei einigen Funktionen eine gpointer user_data zu übergeben. A gpointer ist nur ein void * (dh ein Zeiger auf etwas). Wenn Sie eine Struktur übergeben möchten, benötigen Sie die Adresse der Struktur und nicht die Struktur selbst. Das heißt mit der Adresse, im Gegensatz zu Weitergabe nach Wert.

Anstatt also:

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

schreiben:

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

Dann, wenn Sie in der Callback sind, die user_data Parameter Sie ist ein Zeiger-etwas erhalten. Sie müssen es in einen Zeiger auf Ihre Struktur umwandeln.

Also statt:

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

Sie benötigen das Nachricht Feld mit einem Zeiger des richtigen Typs zuzugreifen (d, nicht user_data), und verwenden Sie den -> Operator, wie Sie die Struktur zuzugreifst über einen Zeiger:

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

Sie scheinen verwirrt über Zeiger, so einen Blick auf diese schöne video about C pointers geben.

Ein weiterer Fehler ist die Verbindung zum delete-event zum Beenden. Dieses Ereignis ist, wenn Sie die Tatsache abfangen möchten, dass der Benutzer auf das Exit-Cross des Fensters geklickt hat oder Alt-F4 zum Beenden verwendet hat und Sie in diesem Moment etwas tun möchten (ein Bestätigungs-Popup anzeigen, einige Daten speichern). Es ist also nicht nötig, dort eine Verbindung herzustellen, die Zerstörung wird passieren (das Signal destroy wird verwendet).

+0

Zuerst danke für die ausführliche Antwort! Nun zu einigen Problemen gibt es noch: immer noch leere Message Box angezeigt. Auch verwirrt über "nutzlos" delete-event: Ich höre Fenster schließen, um sicherzustellen, dass die Anwendung beim Schließen beendet wird, sonst hat Headless App irgendwo im RAM hängen. – LifeOnNet

+0

Für das leere Fenster ist es wahrscheinlich, weil Sie 'gtk_widget_show' anstelle von' gtk_widget_show_all' aufrufen (was rekursiv 'gtk_widget_show' auf dem Widget Kinder aufrufen wird). – liberforce

+0

Über das 'delete-event': Signale haben ein Standardverhalten, das das Richtige tut. Der Standardrückruf für dieses Ereignis gibt 'FALSE' zurück, um das Ereignis weiter zu verbreiten. Der zurückgegebene Wert bestimmt, ob der Signalhandler 'destroy' aufgerufen wird. Und das ist standardmäßig der Fall. Sie haben also nichts zu tun, um das Objekt selbst zu zerstören. – liberforce