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 :

fonction callback avec arguments


Sujet :

GTK+ avec C & C++

  1. #1
    Membre régulier Avatar de YuGiOhJCJ
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2005
    Messages
    206
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2005
    Messages : 206
    Points : 114
    Points
    114
    Par défaut fonction callback avec arguments
    Bonjour,
    j'ai un problème similaire à celui-ci:
    http://www.developpez.net/forums/sho...light=callback

    Je souhaite simplement que lorsqu'on clic sur un bouton, la fonction callback appelée puisse recevoir plusieurs arguments. Le problème est qu'il n'y a qu'un argument possible:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    gulong g_signal_connect( gpointer      *object,
                             const gchar   *name,
                             GCallback     func,
                             gpointer      func_data);
    Je crois que la solution est de donner en argument à la fonction callback une structure:
    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
     
    /* Test struct */
    typedef struct{
    	gchar abc;
    	gchar def;
    }Test;
     
    /* callback function*/
    void callback(GtkWidget *widget, Test data){
    	data.abc = 1;
    	data.def = 2;
    }
     
    /* main function */
    main(){
    Test test1;
    ...
    g_signal_connect(G_OBJECT(window), "delete_event", G_CALLBACK(callback), &test1);
    ...
    }
    Est-ce vraiement ainsi qu'il faut procéder?

  2. #2
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Points : 12 462
    Points
    12 462
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void callback(GtkWidget *widget, Test data)
    Surement pas ... faut jamais changer le type des arguments d'origine, le second tu le laisse de type gpointer !

    Ton appel est correct:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    _signal_connect(G_OBJECT(window), "delete_event", G_CALLBACK(callback), &test1);
    Ensuite pour récupérer ta structure dans ton callback tu peux faire ansi:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    /* callback function*/
    void callback(GtkWidget *widget, gpointer data){
            Test * test = (Test *) data;
     
    	test->abc = 1;
    	test->def = 2;
    }
    Je te signal également que la signature de ton main n'est pas correcte, c'est au choix:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    int main (void)
     
    /* ou */
     
    int main (int argc, char ** argv)
     
    /* ou */
     
    int main (int argc, char * argv [])
    Dans les deux dernière signatures c'est au choix mais c'est identique !
    Mon Site
    Ma bibliothèque de gestion des chaînes de caractères en C

    L'imagination est plus importante que le savoir. A. Einstein

    Je ne répond à aucune question technique par MP, merci d'avance !

  3. #3
    Membre régulier Avatar de YuGiOhJCJ
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2005
    Messages
    206
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2005
    Messages : 206
    Points : 114
    Points
    114
    Par défaut Ok
    ok ouais je me suis trompé sur la fonction main() merci.
    Sinon je vais essayer ce que tu me dis et je donne des nouvelles.ciao.

  4. #4
    Membre régulier Avatar de YuGiOhJCJ
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2005
    Messages
    206
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2005
    Messages : 206
    Points : 114
    Points
    114
    Par défaut
    Citation Envoyé par Franck.H
    Ensuite pour récupérer ta structure dans ton callback tu peux faire ansi:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    /* callback function*/
    void callback(GtkWidget *widget, gpointer data){
            Test * test = (Test *) data;
     
    	test->abc = 1;
    	test->def = 2;
    }
    Je ne suis pas arrivé à implanter ce que tu m'as proposé.
    Peux-tu me dire exactement a quoi correspond:
    -Test
    -test
    -abc
    -def

    J'ai déjà créé une structure.
    J'ai créé une variable du type de la structure.
    Puis dans la fonction callback je tente de récupérer les variables de la variable de type de la structure.
    Merci

  5. #5
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Points : 12 462
    Points
    12 462
    Par défaut
    Montre moi ton code.


    Citation Envoyé par YuGiOhJCJ
    Peux-tu me dire exactement a quoi correspond:
    -Test
    -test
    -abc
    -def
    Bin à la base c'est ta structure donc tu devrais tout savoir à ce sujet mais bon soit:
    • Test : Structure
    • test : Pointeur sur le type de la structure
    • abc, def : Variables membres de la structure tels que tu les as définis toi même !
    Mon Site
    Ma bibliothèque de gestion des chaînes de caractères en C

    L'imagination est plus importante que le savoir. A. Einstein

    Je ne répond à aucune question technique par MP, merci d'avance !

  6. #6
    Membre régulier Avatar de YuGiOhJCJ
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2005
    Messages
    206
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2005
    Messages : 206
    Points : 114
    Points
    114
    Par défaut
    D'accord.
    C'est bien ce que j'ai compris aussi.
    Donc je ne comprends pas pourquoi le compilateur n'est pas content...
    Je vais encore travailler dessus.
    Sinon je vous enverrai ce que me retourne le compilateur et un bout du code.
    Merci à la communauté.

  7. #7
    Membre régulier Avatar de YuGiOhJCJ
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2005
    Messages
    206
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2005
    Messages : 206
    Points : 114
    Points
    114
    Par défaut
    OK. Imaginons maintenant que la structure ressemble à ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    /* Test struct */
    typedef struct{
    	gchar abc;
    	gchar def;
            GtkWidget *ghi;
    }Test;
    Comment je peux faire pour acceder à la valeur associée au pointeur ghi?

  8. #8
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Points : 12 462
    Points
    12 462
    Par défaut
    Citation Envoyé par YuGiOhJCJ
    OK. Imaginons maintenant que la structure ressemble à ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    /* Test struct */
    typedef struct{
    	gchar abc;
    	gchar def;
            GtkWidget *ghi;
    }Test;
    Comment je peux faire pour acceder à la valeur associée au pointeur ghi?
    Si tu passes par un pointeur sur Test (dans le callback par exemple), tu utilise la forme:
    Attention, les pointeurs sont à maîtriser quand même un minimum pour programmer avec GTK+ donc lire des cours sur les pointeurs et les structures ainsi que le passage de pointeurs à des fonctions serais peut-être pas un luxe, même si tu connais, relire ne fait pas de mal


    Bon, vu que tu t'est pas mal embêté sur ce sujet je t'ai fait un petit exemple vite fait qui fonctionne parfaitement (Code::Blocks + MingW):
    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
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    #include <stdlib.h>
    #include <gtk/gtk.h>
    #include <glib/gprintf.h>
     
     
    typedef struct
    {
       gchar abc;
       gchar def;
       GtkWidget * ghi;
    }
    Test;
     
     
    static void cb_remplir (GtkWidget * widget, gpointer data)
    {
       Test * test = (Test *) data;
     
       test->abc = 1;
       test->def = 2;
       test->ghi = widget;
    }
     
    static void cb_lire (GtkWidget * widget, gpointer data)
    {
       Test * test = (Test *) data;
     
       g_printf ("test->abc = %d\n", test->abc);
       g_printf ("test->def = %d\n", test->def);
       g_printf ("test->ghi = %p\n", test->ghi);
    }
     
     
    int main (int argc, char ** argv)
    {
       GtkWidget * p_win    = NULL;
       GtkWidget * p_vbox   = NULL;
       GtkWidget * p_btn [2];
     
       Test test;
     
     
       /*
        * Initialize GTK+
        */
       gtk_init (& argc, & argv);
     
     
       /*
        * Create the main window
        */
       p_win = gtk_window_new           (GTK_WINDOW_TOPLEVEL);
     
       gtk_window_set_title             (GTK_WINDOW (p_win), "Hello, GKT+ !");
       gtk_window_set_default_size      (GTK_WINDOW (p_win), 200, 75);
       gtk_container_set_border_width   (GTK_CONTAINER (p_win), 5);
       gtk_window_set_position          (GTK_WINDOW (p_win), GTK_WIN_POS_CENTER);
       gtk_widget_realize               (p_win);
     
       g_signal_connect                 (p_win, "destroy", gtk_main_quit, NULL);
     
     
       /*
        * Create a vertical box and buttons
        */
       p_vbox = gtk_vbox_new   (TRUE, 5);
       gtk_container_add       (GTK_CONTAINER (p_win), p_vbox);
     
       p_btn [0] = gtk_button_new_with_label ("Remplir la structure");
       gtk_box_pack_start (GTK_BOX (p_vbox), p_btn [0], TRUE, TRUE, 5);
       g_signal_connect (
          G_OBJECT (p_btn [0]),
          "clicked",
          G_CALLBACK (cb_remplir),
          &test
       );
     
       p_btn [1] = gtk_button_new_with_label ("Lire la structure");
       gtk_box_pack_start (GTK_BOX (p_vbox), p_btn [1], TRUE, TRUE, 5);
       g_signal_connect (
          p_btn [1],
          "clicked",
          G_CALLBACK (cb_lire),
          &test
       );
     
     
       /*
        * Enter the main loop
        */
       gtk_widget_show_all (p_win);
       gtk_main ();
     
     
       return EXIT_SUCCESS;
    }
    Mon Site
    Ma bibliothèque de gestion des chaînes de caractères en C

    L'imagination est plus importante que le savoir. A. Einstein

    Je ne répond à aucune question technique par MP, merci d'avance !

  9. #9
    Membre régulier Avatar de YuGiOhJCJ
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2005
    Messages
    206
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2005
    Messages : 206
    Points : 114
    Points
    114
    Par défaut
    Oui effectivement je n'ai pas encore tout compris sur les pointeurs en C. Mais ça ne saurait tarder
    Merci je test ça dès que possible et je redonne des nouvelles

  10. #10
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Points : 12 462
    Points
    12 462
    Par défaut
    Citation Envoyé par YuGiOhJCJ
    Oui effectivement je n'ai pas encore tout compris sur les pointeurs en C. Mais ça ne saurait tarder
    En fait ce que je conseil en générale, c'est de les maîtriser assez bien avant de se lancer dans GTK+ car si tu ne les maîtrises pas du tout et bien y'a d'autres choses que tu ne connais pas du tout également, ce qui peut s'avérer problématique par la suite car GTK+ fait une utilisation massive des pointeurs !

    Donc voilà, en générale je propose de passer plusieurs mois sur l'apprentissage du Langage C puis après, passage à GTK+ si souhaité !
    Mon Site
    Ma bibliothèque de gestion des chaînes de caractères en C

    L'imagination est plus importante que le savoir. A. Einstein

    Je ne répond à aucune question technique par MP, merci d'avance !

  11. #11
    Membre régulier
    Homme Profil pro
    chercheur
    Inscrit en
    Décembre 2012
    Messages
    195
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : chercheur

    Informations forums :
    Inscription : Décembre 2012
    Messages : 195
    Points : 84
    Points
    84
    Par défaut
    Citation Envoyé par Franck.H Voir le message
    Bon, vu que tu t'est pas mal embêté sur ce sujet je t'ai fait un petit exemple vite fait qui fonctionne parfaitement (Code::Blocks + MingW):
    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
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    #include <stdlib.h>
    #include <gtk/gtk.h>
    #include <glib/gprintf.h>
     
     
    typedef struct
    {
       gchar abc;
       gchar def;
       GtkWidget * ghi;
    }
    Test;
     
     
    static void cb_remplir (GtkWidget * widget, gpointer data)
    {
       Test * test = (Test *) data;
     
       test->abc = 1;
       test->def = 2;
       test->ghi = widget;
    }
     
    static void cb_lire (GtkWidget * widget, gpointer data)
    {
       Test * test = (Test *) data;
     
       g_printf ("test->abc = %d\n", test->abc);
       g_printf ("test->def = %d\n", test->def);
       g_printf ("test->ghi = %p\n", test->ghi);
    }
     
     
    int main (int argc, char ** argv)
    {
       GtkWidget * p_win    = NULL;
       GtkWidget * p_vbox   = NULL;
       GtkWidget * p_btn [2];
     
       Test test;
     
     
       /*
        * Initialize GTK+
        */
       gtk_init (& argc, & argv);
     
     
       /*
        * Create the main window
        */
       p_win = gtk_window_new           (GTK_WINDOW_TOPLEVEL);
     
       gtk_window_set_title             (GTK_WINDOW (p_win), "Hello, GKT+ !");
       gtk_window_set_default_size      (GTK_WINDOW (p_win), 200, 75);
       gtk_container_set_border_width   (GTK_CONTAINER (p_win), 5);
       gtk_window_set_position          (GTK_WINDOW (p_win), GTK_WIN_POS_CENTER);
       gtk_widget_realize               (p_win);
     
       g_signal_connect                 (p_win, "destroy", gtk_main_quit, NULL);
     
     
       /*
        * Create a vertical box and buttons
        */
       p_vbox = gtk_vbox_new   (TRUE, 5);
       gtk_container_add       (GTK_CONTAINER (p_win), p_vbox);
     
       p_btn [0] = gtk_button_new_with_label ("Remplir la structure");
       gtk_box_pack_start (GTK_BOX (p_vbox), p_btn [0], TRUE, TRUE, 5);
       g_signal_connect (
          G_OBJECT (p_btn [0]),
          "clicked",
          G_CALLBACK (cb_remplir),
          &test
       );
     
       p_btn [1] = gtk_button_new_with_label ("Lire la structure");
       gtk_box_pack_start (GTK_BOX (p_vbox), p_btn [1], TRUE, TRUE, 5);
       g_signal_connect (
          p_btn [1],
          "clicked",
          G_CALLBACK (cb_lire),
          &test
       );
     
     
       /*
        * Enter the main loop
        */
       gtk_widget_show_all (p_win);
       gtk_main ();
     
     
       return EXIT_SUCCESS;
    }
    Bonjour,

    Je relance ce post car je me bats à mon tour avec l'usage de structures pour passer plusieurs arguments à une fonction callback. L'exemple qui a été donné ci-dessus est très utile, mais il y a tout de même quelque chose qui me chagrine dans ce code. Il s'agit de la ligne 75, ou bien de la ligne 84. L'argument passé ici est un pointeur sur une structure Test. C'est logique, mais ca ne correspond pas au prototype de la fonction callback qui attend ici un argument de type gpointer (voir lignes 15 ou 24). L'argument envoyé et l'argument recu ne sont pas de même type. Comment cela peut-il marcher?

    De fait, dans mes codes, au lien d'envoyer "&test" comme argument, j'ai préféré le caster "(gpointer *)&test". N'est-ce pas préférable?

    Merci pour tout éclaircissement sur ce point.

    Cordialement,

  12. #12
    Modérateur

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2009
    Messages
    1 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2009
    Messages : 1 395
    Points : 2 002
    Points
    2 002
    Par défaut
    Citation Envoyé par eric1708 Voir le message
    De fait, dans mes codes, au lien d'envoyer "&test" comme argument, j'ai préféré le caster "(gpointer *)&test". N'est-ce pas préférable?
    Non, ce n'est pas préférable, c'est même une erreur. Ce serait corect de caster en gpointer, mais pas en gpointer *. Dis toi que gpointer est un void * : ça te permet de caster n'importe quel pointeur, mais tu perds l'information de type. C'est utilisé ici parce GTK ne peut pas connaître le type de la donnée que tu vas passer à g_signal_connect. Il utilise donc un gpointer, c'est à dire un void *, signifiant qu'il est prêt à accepter n'importe quel pointeur, quel que soit son type. Tu peux donc caster explicitement en gpointer, mais à vrai dire, ça ne sert pas à grand chose, car tu te fous du type (tu seras de toute façon obligé de le respécifier dans la callback), donc un cast implicite suffit.

    En C++, on aurait utilisé un template pour ça. En C, c'est du void *.
    Documentation officielle GTK+ 3:
    GTK en C, GTK en Python

    Tutoriels GTK+ 3:
    GTK en C, GTK en Python

    Tutoriels par l'exemple (platform-demos):
    GTK (tous langages)

  13. #13
    Membre régulier
    Homme Profil pro
    chercheur
    Inscrit en
    Décembre 2012
    Messages
    195
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : chercheur

    Informations forums :
    Inscription : Décembre 2012
    Messages : 195
    Points : 84
    Points
    84
    Par défaut
    Citation Envoyé par liberforce Voir le message
    Non, ce n'est pas préférable, c'est même une erreur. Ce serait corect de caster en gpointer, mais pas en gpointer *. Dis toi que gpointer est un void * : ça te permet de caster n'importe quel pointeur, mais tu perds l'information de type. C'est utilisé ici parce GTK ne peut pas connaître le type de la donnée que tu vas passer à g_signal_connect. Il utilise donc un gpointer, c'est à dire un void *, signifiant qu'il est prêt à accepter n'importe quel pointeur, quel que soit son type. Tu peux donc caster explicitement en gpointer, mais à vrai dire, ça ne sert pas à grand chose, car tu te fous du type (tu seras de toute façon obligé de le respécifier dans la callback), donc un cast implicite suffit.

    En C++, on aurait utilisé un template pour ça. En C, c'est du void *.
    Oui, je voulais dire effectivment caster en (gpointer), pas en (gpointer *), évidemment. Erreur de frappe, désolé.

    Ok pour la réponse, très claire. Je trouve plus clair - même donc si pas nécessaire - d'indiquer explicitement le cast, notamment pour faire taire l'analyseur syntaxique (lint) que j'utilise et qui donne un warning..

    Encore merci en tout cas pour l'explication,

    Eric.

Discussions similaires

  1. appel fonction javascript avec argument null
    Par cecile38 dans le forum Servlets/JSP
    Réponses: 0
    Dernier message: 12/01/2011, 10h54
  2. Réponses: 11
    Dernier message: 20/11/2010, 13h08
  3. libsigc++ : attaché une callback avec argument
    Par tinram dans le forum Linux
    Réponses: 0
    Dernier message: 16/01/2009, 18h30
  4. [Dates] fonction date avec argument timestamp
    Par nicoda dans le forum Langage
    Réponses: 3
    Dernier message: 31/01/2008, 16h55
  5. Fonction callback avec arguments ?
    Par sorry60 dans le forum GTK+ avec C & C++
    Réponses: 39
    Dernier message: 07/11/2005, 10h41

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