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 actif Avatar de sorry60
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    802
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 802
    Points : 253
    Points
    253
    Par défaut Fonction callback avec arguments ?
    Bonjour,

    J'aimerais savoir comment passer plusieurs arguments à une fonction callback (servant par exemple au clic sur un bouton).
    J'ai essayé ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    void clic_bouton(GtkWidget* pBouton,gpointer date,int test)
    {
       printf("%d\n",test);
    }
    /*....*/
    int main(int argc,char *argv[])
    {
    /*....*/
    g_signal_connect(G_OBJECT(pBouton),"clicked",G_CALLBACK(clic_bouton),NULL,5);
    return 0;
    }
    Mais c'est pas ça..
    Merci pour votre aide

    Sorry

    Edit : pour être plus précis, j'aimerais que lors du clic sur le bouton, le contenu de deux zones de saisie soit récuperer..il faudrait donc que ma fonction clic_bouton reçoive les 2 Widget zone de saisie en paramètres..

    Ajout de la rédaction :
    Comment passer plusieurs paramètres à une fonction callback ?

  2. #2
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut Re: [GTK] Fonction callback avec arguments ?
    Citation Envoyé par sorry60
    J'aimerais savoir comment passer plusieurs arguments à une fonction callback (servant par exemple au clic sur un bouton).
    Je pense qu'on a déjà expliqué ça.

    En général, une fonction callback est munie d'un paramètre 'utilisateur' de type void *. C'est donc une adresse 'anonyme'. celle-ci est transmise, soit au moment de l'appel de la fonction principale, soit lors de la configuration de l'objet.

    Il suffit que l'adresse passée soit celle d'une structure, pour 'passer' autant de paramètres que l'on veut...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    T data;
     
    f (callback, &data);
    avec
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    callback(void *p_user)
    {
       T *p_data = p_user;
    }
    Ca peut être aussi l'adresse de début d'une liste chainée, d'un tableau...

  3. #3
    Rédacteur/Modérateur
    Avatar de Trap D
    Profil pro
    Inscrit en
    Septembre 2003
    Messages
    4 942
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2003
    Messages : 4 942
    Points : 6 498
    Points
    6 498
    Par défaut
    C'est peut-être aussi simplement un entier transformé pour le passage en pointeur void
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    callback(void *p_user)
    {
       int val = (int) puser;
    }

  4. #4
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par Trap D
    C'est peut-être aussi simplement un entier transformé pour le passage en pointeur void
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    callback(void *p_user)
    {
       int val = (int) puser;
    }
    Quelle horreur ! C'est pas portable !

  5. #5
    Rédacteur/Modérateur
    Avatar de Trap D
    Profil pro
    Inscrit en
    Septembre 2003
    Messages
    4 942
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2003
    Messages : 4 942
    Points : 6 498
    Points
    6 498
    Par défaut
    Citation Envoyé par Emmanuel Delahaye
    Citation Envoyé par Trap D
    C'est peut-être aussi simplement un entier transformé pour le passage en pointeur void
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    callback(void *p_user)
    {
       int val = (int) puser;
    }
    Quelle horreur ! C'est pas portable !
    Ah bon :
    Dans quel cas ?

  6. #6
    Membre éprouvé
    Profil pro
    Eleveur de cornichons
    Inscrit en
    Juin 2002
    Messages
    1 074
    Détails du profil
    Informations personnelles :
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Eleveur de cornichons
    Secteur : Finance

    Informations forums :
    Inscription : Juin 2002
    Messages : 1 074
    Points : 1 166
    Points
    1 166
    Par défaut
    Tu ne peux utiliser que des fonctions qui ont ce prototype :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void fonction(GtkWidget *p, gpointer data);
    Donc dans ton g_signal_connect, tu as un paramètre en trop. Idem dans ta fonction callback.
    Comme l'a dit Emmanuel, tu peux mettre tes composants dans une structure. Comme ça, tu passes la structure en paramètre.
    Exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    typedef struct {
    GtkWIdget *pWindow ;
    GtkWidget *pLabel ;
    }win ;
     
    /* ... */
    Mais penses à faire le cast au moment où tu la passes car je te rappelle le type gpointer c'est équivalent au void* .

    Sinon, une autre solution plus compliquée je trouve consiste à passer la box (si t'en utilises) et t'accéder à chaque élément de la box via une liste chainée déjà définie. En effet, la box est l'ancre d'une liste donc chaque maillon est un composant (les maillons sont insérés dans l'ordre d'insertion de tes composants dans la box).

    Nas'

  7. #7
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par Trap D
    Citation Envoyé par Emmanuel Delahaye
    Citation Envoyé par Trap D
    C'est peut-être aussi simplement un entier transformé pour le passage en pointeur void
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    callback(void *p_user)
    {
       int val = (int) puser;
    }
    Quelle horreur ! C'est pas portable !
    Ah bon :
    Dans quel cas ?
    Le langage C ne garantit pas qu'un int tienne dans un pointeur et inversement. On pourrait très bien avoir un int 32-bit et un pointeur 16-bit.

  8. #8
    Rédacteur/Modérateur
    Avatar de Trap D
    Profil pro
    Inscrit en
    Septembre 2003
    Messages
    4 942
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2003
    Messages : 4 942
    Points : 6 498
    Points
    6 498
    Par défaut
    Merci de l'info, je ne le savais pas.

  9. #9
    Membre actif Avatar de sorry60
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    802
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 802
    Points : 253
    Points
    253
    Par défaut
    Merci pour votre aide, j'ai donc décidé de faire un tableau de Zones de saisie, et de la passer dans la callback :
    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
     
    void connection(GtkWidget* pBoutonConnection,gpointer data)
    {
      printf("%s\n",gtk_entry_get_text(data[0]));
    }
     
    int main(int argc,char* argv[])
    {
    /*...*/
    GtkWidget* pZSaisies[3];
    /*...*/
    g_signal_connect(G_OBJECT(pBouton),"clicked",G_CALLBACK(connection),(GtkWidget*) pZSaisies);
    /*...*/
    return 0;
    }
    Mais ça ne passe pas à la compilation
    cc1: warnings being treated as errors
    client.c: In function ‘connection’:
    client.c:5: attention : dereferencing ‘void *’ pointer
    client.c:5: erreur: utilisation invalide d'expression void
    client.c: In function ‘main’:
    client.c:52: erreur: le transtypage spécifie un type de tableau
    make: *** [client.o] Erreur 1
    J'ai du bien mal faire..

  10. #10
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 381
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 381
    Points : 41 582
    Points
    41 582
    Par défaut
    Citation Envoyé par Emmanuel Delahaye
    Le langage C ne garantit pas qu'un int tienne dans un pointeur et inversement. On pourrait très bien avoir un int 32-bit et un pointeur 16-bit.
    Par contre, certaines API utilises des types définis exprès pour cela (INT_PTR chez Microsoft, et il doit y avoir la même chose pour diverses APIs ou Libs utilisant des callbacks...

  11. #11
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par sorry60
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    void connection(GtkWidget* pBoutonConnection,gpointer data)
    {
      printf("%s\n",gtk_entry_get_text(data[0]));
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    client.c:5: attention : dereferencing ‘void *’ pointer
    Evidemment, tu ne peux pas déférérencer le pointeur anonyme. Pourquoi crois-tu que je sois passé par un pointeur local typé ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    callback(void *p_user)
    {
       T *p_data = p_user;
    }

  12. #12
    Membre actif Avatar de sorry60
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    802
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 802
    Points : 253
    Points
    253
    Par défaut
    Je ne suis pas sur d'avoir compris, j'ai fait ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    void connection(GtkWidget* pBoutonConnection,gpointer data)
    {
      GtkWidget* tab = data;
      printf("%s\n",gtk_entry_get_text(tab[0]));
    }
    J'ai ce warning :
    client.c: In function ‘connection’:
    client.c:6: erreur: incompatible type for argument 1 of ‘gtk_entry_get_text’

  13. #13
    Membre actif Avatar de sorry60
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    802
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 802
    Points : 253
    Points
    253
    Par défaut
    L'erreur doit etre ailleurs car meme en castant le warning est là

    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
     
    void connection(GtkWidget* pBoutonConnection,gpointer data)
    {
      GtkWidget* tab = (GtkWidget*)data;
      printf("%s\n",gtk_entry_get_text(tab[0]));
    }
     
    int main()
    /*...*/
    GtkWidget* pZSaisies[3];
    /*...*/
    g_signal_connect(G_OBJECT(pBoutons[0]),"clicked",G_CALLBACK(connection),&pZSaisies);
    /*...*/
    return 0;
    }
    client.c: In function ‘connection’:
    client.c:6: erreur: incompatible type for argument 1 of ‘gtk_entry_get_text’
    make: *** [client.o] Erreur 1

  14. #14
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par sorry60
    Je ne suis pas sur d'avoir compris, j'ai fait ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    void connection(GtkWidget* pBoutonConnection,gpointer data)
    {
      GtkWidget* tab = data;
      printf("%s\n",gtk_entry_get_text(tab[0]));
    }
    J'ai ce warning :
    client.c: In function ‘connection’:
    client.c:6: erreur: incompatible type for argument 1 of ‘gtk_entry_get_text’
    Quel est le type attendu par gtk_entry_get_text() ?

    Je soupçonne un
    donc
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    void connection(GtkWidget* pBoutonConnection,gpointer data)
    {
      GtkWidget* tab = data;
      printf("%s\n",gtk_entry_get_text(tab + 0));
    }

  15. #15
    Membre actif Avatar de sorry60
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    802
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 802
    Points : 253
    Points
    253
    Par défaut
    En effet gtk_entry_get_text n'attend pas un GtkWidget* mais un GtkEntry*
    G_CONST_RETURN gchar* gtk_entry_get_text(GtkEntry *entry);
    Il faut donc utiliser la macro GTK_ENTRY pour caster le GtkWidget* en GtkEntry*, désolé j'aurais du y penser plus tot

    Maintenant le code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    void connection(GtkWidget* pBoutonConnection,gpointer data)
    {
      GtkWidget* tab = (GtkWidget*)data;
      printf("%s\n",gtk_entry_get_text(GTK_ENTRY(tab+0)));
    }
    La compil passe sans probleme, mais à l'execution, quand je clicque sur le bouton j'ai le célèbre "Erreur de segmentation"
    (progClient:7655): GLib-GObject-WARNING **: invalid uninstantiatable type `(null)' in cast to `GtkEntry'

    (progClient:7655): Gtk-CRITICAL **: gtk_entry_get_text: assertion `GTK_IS_ENTRY (entry)' failed
    Erreur de segmentation

  16. #16
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par sorry60
    En effet gtk_entry_get_text n'attend pas un GtkWidget* mais un GtkEntry*
    alors il fait lui passer ce qu'il attend. Et c'est pas une histoire de cast.

  17. #17
    Membre actif Avatar de sorry60
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    802
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 802
    Points : 253
    Points
    253
    Par défaut
    Citation Envoyé par Emmanuel Delahaye
    Citation Envoyé par sorry60
    En effet gtk_entry_get_text n'attend pas un GtkWidget* mais un GtkEntry*
    alors il fait lui passer ce qu'il attend. Et c'est pas une histoire de cast.
    Je lui ai passé ce qu'il attend, grâce à la macro.

  18. #18
    Membre actif Avatar de sorry60
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    802
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 802
    Points : 253
    Points
    253
    Par défaut
    J'ai testé en mettant dans le main :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    printf("%s\n",gtk_entry_get_text(GTK_ENTRY(pZoneSaisies[0])));
    Cela fonctionne parfaitement.
    Donc le probleme vient du passage des arguments à la fonction callback

  19. #19
    Membre actif Avatar de sorry60
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    802
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 802
    Points : 253
    Points
    253
    Par défaut
    Ca marche aussi parfaitement si j'appelle ma fonction en lui passant un element du tableau :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    g_signal_connect(G_OBJECT(pBoutons[0]),"clicked",G_CALLBACK(connection),pZSaisies[0]);
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    void connection(GtkWidget* pBouton,gpointer data)
    {
       printf("%s\n",gtk_entry_get_text(GTK_ENTRY(data)));
    }
    Mais c'est pas du tout ce qui m'interesse

  20. #20
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par sorry60
    J'ai testé en mettant dans le main :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    printf("%s\n",gtk_entry_get_text(GTK_ENTRY(pZoneSaisies[0])));
    Cela fonctionne parfaitement.
    Donc le probleme vient du passage des arguments à la fonction callback
    C'est un tableau de pointeurs ?
    Dans ce cas, c'est bien
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    printf("%s\n",gtk_entry_get_text(GTK_ENTRY(pZoneSaisies[0])));
    et non
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    printf("%s\n",gtk_entry_get_text(GTK_ENTRY(pZoneSaisies+0)));
    comme je l'avais cru...

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

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

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