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

C++ Discussion :

Appel fonction member par pthread_create


Sujet :

C++

  1. #1
    Membre confirmé Avatar de LinuxUser
    Inscrit en
    Avril 2007
    Messages
    857
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 857
    Points : 616
    Points
    616
    Par défaut Appel fonction member par pthread_create
    Bonjour,

    Je souhaiterais savoir comment utiliser les pthread pour appeler une fonction membre de ma classe.

    Voici schematiquement ce que je voudrais faire:


    .h
    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
     
    #include <pthread.h>
     
    struct pthread_data
    {
      double a;
      double b;
      double c;
    }
    class MyClass
    {
      void anotherMemberFunction();
      void memberFunctionToCall(double a, double b, double c);
     
      static void *threadHandler(void *args);
     
      struct pthread_data m_threads[2];
    }
    .cpp
    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
    #include "MyClass.h"
    void MyClass::anotherMemberFunction()
    {
      ...
      iret1 = pthread_create( &thread1, NULL, MyClass::threadHandler,
    						(void*) &m_threads[1]);
      iret2 = pthread_create( &thread1, NULL, MyClass::threadHandler,
    						(void*) &m_threads[2]);
      ...
    }
     
    void *MyClass::threadHandler(void *args)
    {
      struct pthread_data *data;
      data = (struct pthread_data*) args;
     
      memberFunctionToCall(data->a, data->b, data->c);
    }
    J'obtiens l'erreur suivante:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    erreur: cannot call member function ‘void MyClass::memberFunctionToCall(double&, double&, double&)’ without object
    J'insiste sur le fait que je souhaite appeler la function "memberFunctionToCall" avec l'objet courant (et toutes les valeurs de ses membres au moment de l'appel) et donc éviter toute solution qui créerait un objet juste pour effetuer l'appel, du genre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    void handler(void *args)
    {
     MyClass c;
     c.memberFunctionToCall(...);
    }
    Merci de votre aide.

  2. #2
    Membre averti
    Homme Profil pro
    Inscrit en
    Juillet 2012
    Messages
    200
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Bénin

    Informations forums :
    Inscription : Juillet 2012
    Messages : 200
    Points : 342
    Points
    342
    Par défaut
    Bonsoir. La fonction threadHandler() étant déclaré static, je ne pense pas qu'il soit possible d'y faire appel memberFunctionToCall qui n'est pas static.
    La solution serait peut être d'ajouter à la struct pthread_data un membre de type MyClass*

  3. #3
    Membre averti
    Homme Profil pro
    Inscrit en
    Juillet 2012
    Messages
    200
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Bénin

    Informations forums :
    Inscription : Juillet 2012
    Messages : 200
    Points : 342
    Points
    342
    Par défaut
    La solution est donc
    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
     
    class MyClass;
     
    struct pthread_data
    {
      double a;
      double b;
      double c;
      MyClass *o; // Représentera un pointeur sur l'objet courant
    };
     
    class MyClass
    {
      void anotherMemberFunction();
      void memberFunctionToCall(double a, double b, double c, MyClass *o);
     
      static void *threadHandler(void *args);
     
      struct pthread_data m_threads[2];
    }
     
    void *MyClass::threadHandler(void *args)
    {
      struct pthread_data *data;
      data = (struct pthread_data*) args;
     
      memberFunctionToCall(data->a, data->b, data->c, data->o);
    }

  4. #4
    Expert éminent sénior
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 071
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Val de Marne (Île de France)

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

    Informations forums :
    Inscription : Février 2005
    Messages : 5 071
    Points : 12 116
    Points
    12 116
    Par défaut
    C'est plus :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    void *MyClass::threadHandler(void *args)
    {
      struct pthread_data *data;
      data = reintrepret_cast<struct pthread_data*> args;
     
      data->o->memberFunctionToCall(data->a, data->b, data->c, data->o);
    }
    Mais faut ajouter les vérifications habituelles.

  5. #5
    Membre confirmé Avatar de LinuxUser
    Inscrit en
    Avril 2007
    Messages
    857
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 857
    Points : 616
    Points
    616
    Par défaut
    Merci pour vos réponses, mais c'est le genre de solution que je voulais éviter.

    D'ailleurs je vois pas comment utiliser cela lors de l'appel à thread_create:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    m_threads[1]->o = ?; // this?
    iret1 = pthread_create( &thread1, NULL, MyClass::threadHandler,
    						(void*) &m_threads[1]);

  6. #6
    Membre averti
    Homme Profil pro
    Inscrit en
    Juillet 2012
    Messages
    200
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Bénin

    Informations forums :
    Inscription : Juillet 2012
    Messages : 200
    Points : 342
    Points
    342
    Par défaut
    @bacelar
    @LinuxUser
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    m_threads[1]->o = this;
    Je pense que c'est cela.
    Cela dit, il y a un autre problème caché dans votre code. Avec la déclaration
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    struct pthread_data m_threads[2];
    et ensuite
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    iret2 = pthread_create( &thread1, NULL, MyClass::threadHandler,
    						(void*) &m_threads[2]); // c'est plutôt &m_threads[0] et ensuite &m_threads[1]
    Ca sent la SEGFAULT

  7. #7
    Membre confirmé Avatar de LinuxUser
    Inscrit en
    Avril 2007
    Messages
    857
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 857
    Points : 616
    Points
    616
    Par défaut
    Oui, c est une erreur d'inattention, je me suis juste trompé d'indice, il fallait lire:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     iret1 = pthread_create( &thread1, NULL, MyClass::threadHandler,
    						(void*) &m_threads[0]);
      iret2 = pthread_create( &thread1, NULL, MyClass::threadHandler,
    						(void*) &m_threads[1]);
    Par contre, je suis pas persuadé pour le "this" lors de l'appel .

  8. #8
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    26 859
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 26 859
    Points : 218 580
    Points
    218 580
    Billets dans le blog
    120
    Par défaut
    Bonjour,

    J'ai une technique "bizarre" pour les threads POSIX en C++. Je passe un pointeur de la classe à mon thread et bien sur, comme il a été transformé en void*, je le caste dans le thread -> https://code.google.com/p/lpowerprob...ntation.cpp#43
    (On remarquera une possible erreur avec l'assert, mais bon... passons.)
    Et aussi, je mets en tant qu'amie, la fonction qui est lancée dans le thread -> https://code.google.com/p/lpowerprob...imentation.hpp ainsi, j'ai accès à mes fonctions/variables membres, une fois que je retourne dans ma classe, tranquillement.
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  9. #9
    Membre confirmé Avatar de LinuxUser
    Inscrit en
    Avril 2007
    Messages
    857
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 857
    Points : 616
    Points
    616
    Par défaut
    Donc dans mon cas, il faudrait:

    1. Que j'ajoute un pointeur de ma classe dans la structure:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    struct pthread_data
    {
      double a;
      double b;
      double c;
      MyClass *o; // Représentera un pointeur sur l'objet courant
    };
    2. Que je vire le "static" de ma fonction appelée dans le thread "threadHandler":

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void *threadHandler(void *args); // static supprimé
    C'est bien cela?

    3. Que j'ajoute le mot clef friend à la place du static supprimé en 2.:


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    friend void *threadHandler(void *args); // friend ajouté
    Puis que j'appelle de la manière suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    m_threads[1]->o = this;
    iret1 = pthread_create( &thread1, NULL, MyClass::threadHandler,
    						(void*) &m_threads[0]);

  10. #10
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Citation Envoyé par LittleWhite Voir le message
    Et aussi, je mets en tant qu'amie, la fonction qui est lancée dans le thread
    Perso je la mets carrément membre static
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  11. #11
    Membre confirmé Avatar de LinuxUser
    Inscrit en
    Avril 2007
    Messages
    857
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 857
    Points : 616
    Points
    616
    Par défaut
    C'etait en static, mais lors de l'appel de la fonction membre à l'interieur de cette fonction, j'obtiens le message suivant:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    erreur: cannot call member function ‘void MyClass::memberFunctionToCall(double&, double&, double&)’ without object
    C'est le problème que j'ai à l'origine.

  12. #12
    Membre averti
    Homme Profil pro
    Inscrit en
    Juillet 2012
    Messages
    200
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Bénin

    Informations forums :
    Inscription : Juillet 2012
    Messages : 200
    Points : 342
    Points
    342
    Par défaut
    Vous avez fait comme l'a dit bacelar ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    struct pthread_data
    {
      double a;
      double b;
      double c;
      MyClass *o; // Représentera un pointeur sur l'objet courant
    };
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    class MyClass
    {
      void anotherMemberFunction();
      void memberFunctionToCall(double a, double b, double c); // Plus besoin du paramètre de type MyClass*
     
      static void *threadHandler(void *args);
     
      struct pthread_data m_threads[2];
    }
    Ensuite dans la fonction membre static
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    void *MyClass::threadHandler(void *args)
    {
      struct pthread_data *data;
      data = reintrepret_cast<struct pthread_data*> args;
     
      data->o->memberFunctionToCall(data->a, data->b, data->c); // 
    }
    Cela devrait normalement marcher...

  13. #13
    Membre confirmé Avatar de LinuxUser
    Inscrit en
    Avril 2007
    Messages
    857
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 857
    Points : 616
    Points
    616
    Par défaut
    Pour mettre l'objet dans al structure, c'est quoi la bonne méthode, simplement

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    m_threads[1]->o = this;
    Ou est-ce qu il faut d'abord alloué la mémoire pour copier l'objet avant, du genre:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    m_threads[1]->o = new Class;
    m_threads[1]->o = this;

  14. #14
    Membre averti
    Homme Profil pro
    Inscrit en
    Juillet 2012
    Messages
    200
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Bénin

    Informations forums :
    Inscription : Juillet 2012
    Messages : 200
    Points : 342
    Points
    342
    Par défaut
    Pour mettre l'objet dans la structure, comme vous dites c'est
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    m_threads[1]->o = this;

  15. #15
    Membre confirmé Avatar de LinuxUser
    Inscrit en
    Avril 2007
    Messages
    857
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 857
    Points : 616
    Points
    616
    Par défaut
    Ca ne marche pas, cela provoque une "seg fault".

  16. #16
    Membre averti
    Homme Profil pro
    Inscrit en
    Juillet 2012
    Messages
    200
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Bénin

    Informations forums :
    Inscription : Juillet 2012
    Messages : 200
    Points : 342
    Points
    342
    Par défaut
    OK. Les threads doivent fonctionner sur un objet particulier ou avec plusieurs objets ?

  17. #17
    Membre confirmé Avatar de LinuxUser
    Inscrit en
    Avril 2007
    Messages
    857
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 857
    Points : 616
    Points
    616
    Par défaut
    Un seul objet, l'objet courant de ma classe:

    MyClass.h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    #include <pthread.h>
     
     
    class MyClass
    {
      ...
      struct pthread_data
     {
        double a;
        double b;
        double c;
        MyClass *pMyClass;
      }
    }
    MyClass.cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    void MyClass::anotherMemberFunction()
    {
      ...
      m_threads[0]->o = ???; // je ne sais pas comment récupérer l'objet courant MyClass tout en allouant l'espace mémoire dans la structure
      iret1 = pthread_create( &thread1, NULL, MyClass::threadHandler,
    						(void*) &m_threads[0]);
      ...
      m_threads[1]->o = ???; // idem
      iret2 = pthread_create( &thread1, NULL, MyClass::threadHandler,
    						(void*) &m_threads[1]);
      ...
    }

  18. #18
    Membre confirmé Avatar de LinuxUser
    Inscrit en
    Avril 2007
    Messages
    857
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 857
    Points : 616
    Points
    616
    Par défaut
    En fait la seg fault venait du fait que je m'étais trompé d'indice dans mon tableau de structure :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    m_threads[1] au lieu de m_threads[0]
    m_threads[2] au lieu de m_threads[1] // seg fault!!!
    Donc là, je n'ai plus de seg fault, mais mes résultas sont faux, je ne sais pas si c'est un problème de synchronisation où de partage de mémoire (les deux objets travaillent sur le même objet alors qu ils devraient avoir chacun leur copie).

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    m_threads[0]->o = this;
    m_threads[1]->o = this;
    Devrait peut être :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    m_threads[0]->o = ???; // copie objet courant
    m_threads[1]->o = ???;// copie objet courant

  19. #19
    Membre averti
    Homme Profil pro
    Inscrit en
    Juillet 2012
    Messages
    200
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Bénin

    Informations forums :
    Inscription : Juillet 2012
    Messages : 200
    Points : 342
    Points
    342
    Par défaut
    Citation Envoyé par LinuxUser
    En fait la seg fault venait du fait que je m'étais trompé d'indice dans mon tableau de structure
    Je l'avais dis ça...
    Plus sérieusement si la fonction membre memberFunctionToCall modifie l'état de l'objet, il est normal que les deux threads concurrentiellement accèdent à l'objet alors qu'il est dans un état incorrect

  20. #20
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    26 859
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 26 859
    Points : 218 580
    Points
    218 580
    Billets dans le blog
    120
    Par défaut
    Citation Envoyé par Bousk Voir le message
    Perso je la mets carrément membre static
    Je n'aime pas, car je veux garder accès aux autres fonctions/membres, de la classe. À moins que vous ne parliez de la fonction appelée par pthread_create (le pthread_handler) ?
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

Discussions similaires

  1. [PHP-JS] Appel de fonction PHP par JS
    Par pat06 dans le forum Langage
    Réponses: 5
    Dernier message: 29/11/2007, 09h03
  2. Réponses: 6
    Dernier message: 07/06/2007, 14h27
  3. Appel de fonctions php par variable
    Par WagaSeb dans le forum Langage
    Réponses: 2
    Dernier message: 02/06/2007, 11h06
  4. appeler une fonction définit par l'utilisateur
    Par paumi dans le forum C++Builder
    Réponses: 5
    Dernier message: 22/05/2007, 00h00
  5. [VB.Net] Problème appel fonction par un bouton
    Par balibo dans le forum ASP.NET
    Réponses: 4
    Dernier message: 25/11/2005, 10h48

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