IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

GTK+ avec C & C++ Discussion :

Valeur de retour étrange de g_signal_connect


Sujet :

GTK+ avec C & C++

  1. #1
    Membre confirmé
    Inscrit en
    Mars 2007
    Messages
    134
    Détails du profil
    Informations forums :
    Inscription : Mars 2007
    Messages : 134
    Par défaut Valeur de retour étrange de g_signal_connect
    Bonjour,

    j'ai vu dans différents forum que, pour retourner plusieurs paramètres avec g_signal_connect, un moyen était d'utiliser une structure. Voici donc ce que j'ai fait:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
     
    typedef struct {
        GtkWidget* window_to_update;
        guchar* current_view;
        guchar selected_view;
    }
    strdef;
     
    GtkWidget* create_main_window(void) {
        // ...
        guchar crt_view = 0;
        strdef param = {v_box_2, &crt_view, 0};
        button1 = gtk_button_new_with_label("button1");
        button2 = gtk_button_new_with_label("button2");
        button3 = gtk_button_new_with_label("button3");
        param.selected_view = (guchar) 0;
        g_signal_connect(GTK_BUTTON(button1), "clicked", G_CALLBACK(fct), &param);
        param.selected_view = (guchar) 1;
        g_signal_connect(GTK_BUTTON(button2), "clicked", G_CALLBACK(fct), &param);
        param.selected_view = (guchar) 2;
        g_signal_connect(GTK_BUTTON(button3), "clicked", G_CALLBACK(fct), &param);
    }
     
    static void fct(GtkButton *widget, gpointer data) {
        strdef* test = (strdef*) data;
        g_print("%i\n",(guchar) test->selected_view);
    }
    Le retour pour le premier bouton est bien 0. Par contre, pour le second, j'ai 208 et pour le troisième, 48 ?

    Je m'attendais à 0, 1 et 2.

    Quelqu'un peut m'éclairer ?

    Merci.

  2. #2
    Rédacteur

    Avatar de gege2061
    Femme Profil pro
    Administrateur de base de données
    Inscrit en
    Juin 2004
    Messages
    5 840
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur de base de données

    Informations forums :
    Inscription : Juin 2004
    Messages : 5 840
    Par défaut
    Bonjour,

    une fois sortie de la fonction create_main_window ta variable param n'existe plus !

  3. #3
    Membre confirmé
    Inscrit en
    Mars 2007
    Messages
    134
    Détails du profil
    Informations forums :
    Inscription : Mars 2007
    Messages : 134
    Par défaut
    Mais pourtant, quand je clique sur un bouton, la fonction de callback réagit donc j'ai l'impression de toujours être dans la fonction create_main_window grâce à gtk_main() qui si je ne me trompe pas, génére une boucle infinie sur ma fenêtre principale :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    int main(int argc, char *argv[]) {
        GtkWidget *main_window = NULL;
        gtk_init(&argc, &argv);
        main_window = create_main_window();
        gtk_widget_show(main_window);
        gtk_main();
        return EXIT_SUCCESS;
    }

  4. #4
    Membre éprouvé
    Avatar de Shugo78
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 119
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 119
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    g_signal_connect(GTK_BUTTON(button1), "clicked", G_CALLBACK(fct), &param);
        param.selected_view = (guchar) 1;
        g_signal_connect(GTK_BUTTON(button2), "clicked", G_CALLBACK(fct), &param);
        param.selected_view = (guchar) 2;
        g_signal_connect(GTK_BUTTON(button3), "clicked", G_CALLBACK(fct), &param);
    g_signal_connect attend un premier paramètre de type Gobject, pour cela, tu dois utiliser le macro de conversion G_OBJECT sur ton bouton, donc, moi je verais plutôt ça comme ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    g_signal_connect(G_OBJECT(GTK_BUTTON(button1)), "clicked", G_CALLBACK(fct), &param);
        param.selected_view = (guchar) 1;
        g_signal_connect(G_OBJECT(GTK_BUTTON(button2)), "clicked", G_CALLBACK(fct), &param);
        param.selected_view = (guchar) 2;
        g_signal_connect(G_OBJECT(GTK_BUTTON(button3)), "clicked", G_CALLBACK(fct), &param);
    Citation Envoyé par gege2061
    une fois sortie de la fonction create_main_window ta variable param n'existe plus !
    param est pourtant ransmit en argument à la fonction callback sous forme de gpointer

  5. #5
    Rédacteur

    Avatar de gege2061
    Femme Profil pro
    Administrateur de base de données
    Inscrit en
    Juin 2004
    Messages
    5 840
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur de base de données

    Informations forums :
    Inscription : Juin 2004
    Messages : 5 840
    Par défaut
    Citation Envoyé par Shugo78
    g_signal_connect attend un premier paramètre de type Gobject, pour cela, tu dois utiliser le macro de conversion G_OBJECT sur ton bouton, donc, moi je verais plutôt ça comme ça :
    Le double cast n'est pas utile :
    Suffit.

    Citation Envoyé par Shugo78
    param est pourtant ransmit en argument à la fonction callback sous forme de gpointer
    Et ? Si la variable n'existe plus, tu peux toujours utiliser son adresse, à part des problèmes ça n'apporte pas grand chose.

  6. #6
    Membre confirmé
    Inscrit en
    Mars 2007
    Messages
    134
    Détails du profil
    Informations forums :
    Inscription : Mars 2007
    Messages : 134
    Par défaut
    Selon la doc GTK, le retour de la fonction callback associée à l'évènement activate est :

    void user_function (GtkButton *widget, gpointer user_data) : Run First / Action
    C'est pour cela que j'avais choisi la macro GTK_BUTTON.

    Dans tous les cas, maintenant, j'utilise aussi un objet GTK. Voici mon code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    parameters_to_pass.selected_view = (guchar) 0;
    g_signal_connect(G_OBJECT(button1), "activate", G_CALLBACK(fct), (strdef*) &param);
    et

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    static void update_window_selector(GtkWidget *widget, gpointer data) {
        strdef* test = (strdef*) data;
        g_print("%i\n",(guchar) test->selected_view);
    }
    Ca ne marche pas non plus. Je n'ai pas trouvé d'autre solution pour le moment. Je suis bloqué :-( .

  7. #7
    Membre éprouvé
    Avatar de Shugo78
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 119
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 119
    Par défaut
    En fait, la solution serait(je pense) de lancer la bouclé événementielle dans ta fonction create_main_window
    [EDIT] Ou alors, au pire, de créer une variable globale, à utiliser en derner recours

  8. #8
    Membre confirmé
    Inscrit en
    Mars 2007
    Messages
    134
    Détails du profil
    Informations forums :
    Inscription : Mars 2007
    Messages : 134
    Par défaut
    Je sais que les variables globales peuvent résoudre mon problème mais cela ne donne pas un codage propre donc je ne veux pas les utiliser.

    Par contre, je ne comprends toujours pas comment la variable peut être détruite. Durant toute l'exécution du programme, les fenêtres sont affichées donc non détruites et les fonctions g_signal_connect qui se trouvent dans create_main_window peuvent être appelée à tout moment donc également non détruites. Pourquoi la variable param serait, elle, détruite avant tout le reste ?

  9. #9
    Membre éprouvé
    Avatar de Shugo78
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 119
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 119
    Par défaut
    Ca marche en lancant la boucle événementielle depuis create_main_window ?
    Citation Envoyé par julieng31
    Par contre, je ne comprends toujours pas comment la variable peut être détruite. Durant toute l'exécution du programme, les fenêtres sont affichées donc non détruites et les fonctions g_signal_connect qui se trouvent dans create_main_window peuvent être appelée à tout moment donc également non détruites. Pourquoi la variable param serait, elle, détruite avant tout le reste ?
    Les variables sont locales(propres à la fonction), dès qu'une fonction externe est éxécutée, les variables ne sont pas détruites mais elles n'éxistent pas dans cette fonction, dès que tu reviens dans ta fonction create_main_window, elles éxistent à nouveau
    Et elles ne sont détruites que quand tu sors de la fonction create_window_new, les fenêtres sont toujours affiché quand tu es dans le main, mais essayes de modifier le titre par exemple

  10. #10
    Membre confirmé
    Inscrit en
    Mars 2007
    Messages
    134
    Détails du profil
    Informations forums :
    Inscription : Mars 2007
    Messages : 134
    Par défaut
    Les variables sont locales (propres à la fonction), dès qu'une fonction externe est éxécutée, les variables ne sont pas détruites mais elles n'éxistent pas dans cette fonction, dès que tu reviens dans ta fonction create_main_window, elles éxistent à nouveau.
    Je suis d'accord que la portée des variables crées dans les fonctions ne se limite qu'à la fonction elle même. Or, là, je passe un pointeur, ce qui devrait rendre la variable accessible à la fonction "externe".

    Donc si j'ai bien compris, le GTK maintient les fenêtres hors de la fonction create_main_window. Je pensais que le main créait une boucle, je ne sais pas trop où d'ailleurs, dans la fonction create_main_window pour avoir accès aux fonctions fct_X. Dans ce cas, je comprends mieux.

    J'essaye ta solution (déplacer la boucle évenementielle) dès demain.

  11. #11
    Membre éprouvé
    Avatar de Shugo78
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 119
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 119
    Par défaut
    Non, la variable originale est détruite, ce que tuas c'est son adresse, qui après sa déstruction ne correspond plus à rien
    Citation Envoyé par julieng31
    Donc si j'ai bien compris, le GTK maintient les fenêtres hors de la fonction create_main_window
    Les pointeurs ne servent qu'à contenir des informations

  12. #12
    Membre confirmé
    Inscrit en
    Mars 2007
    Messages
    134
    Détails du profil
    Informations forums :
    Inscription : Mars 2007
    Messages : 134
    Par défaut
    J'ai déclaré mon param dans le main :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    guchar current_view = 0;
    strdef param = {NULL, &current_view, 0};
    et je l'ai passé en paramètre à ma fonction create_main_window:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    create_main_window(&param);
    Dans ma fonction de connection du signal activate, j'ai maintenant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    g_signal_connect(G_OBJECT(search), "activate", G_CALLBACK(update_window_selector), param);
    Ca progresse parce que j'obtiens toujours la valeur X de la dernière assignation :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    param->selected_view = (guchar) X;
    Donc ma variable n'est plus détruite. Maintenant, j'aimerais avoir une valeur différente pour chaque bouton. J'ai essayé de mettre la boucle évènementielle autour des fonctions g_signal_connect et des assignations de param->selected_view mais apparemment, je ne peux rien mettre à l'intérieur de la fonction gtk_main() sinon, j'obtiens une erreur.

  13. #13
    Membre éprouvé
    Avatar de Shugo78
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 119
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 119
    Par défaut
    Il faudrait tout déclarer dans le main, puis tous passer en arguments dans ce cas

Discussions similaires

  1. Valeur de retour d'une procédure stockée
    Par Rudyweb dans le forum MFC
    Réponses: 4
    Dernier message: 25/02/2005, 17h52
  2. fonction operator, valeur de retour
    Par butch dans le forum C++
    Réponses: 21
    Dernier message: 20/09/2004, 10h30
  3. [VB6] Valeur de retour pour une Form
    Par preverse dans le forum VB 6 et antérieur
    Réponses: 3
    Dernier message: 17/08/2004, 17h16
  4. Valeur de retour d'une procédure externe
    Par elekis dans le forum x86 32-bits / 64-bits
    Réponses: 4
    Dernier message: 16/04/2004, 16h45
  5. Pourquoi une seule valeur de retour pour les fonctions ?
    Par Bruno75 dans le forum Langages de programmation
    Réponses: 33
    Dernier message: 18/01/2004, 13h58

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo