95 votes

pthread Fonction à partir d'une Classe

Disons que j'ai une classe comme

class c{...
    void *print(void *){ cout << "Hello"; }
}

Et puis j'ai un vecteur de c

vector<c> classes; pthread_t t1;
classes.push_back(c());
classes.push_back(c());

Maintenant, je veux créer un thread sur c.print();

Et la Suite me donne un problème pthread_create(&t1, NULL, &c[0].print, NULL);

Error Ouput: cannot convert ‘void* (tree_item::*)(void*)' to ‘void* (*)(void*)' 
for argument ‘3' to ‘int pthread_create(pthread_t*, const pthread_attr_t*,
void* (*)(void*), void*)'

160voto

Adam Rosenfield Points 176408

Vous ne pouvez pas faire de la manière dont vous l'ai écrit parce que le C++ fonctions de membre de classe ont une face cachée this paramètre transmis. pthread_create() n'a aucune idée de la valeur de this à utiliser, donc si vous essayez de contourner le compilateur par la coulée de la méthode à un pointeur de fonction du type approprié, vous obtiendrez un segmetnation faute. Vous devez utiliser une méthode de classe statique (qui n'a pas d' this paramètre), ou une simple fonction ordinaire pour l'amorçage de la classe:

class C
{
public:
    void *hello(void)
    {
        std::cout << "Hello, world!" << std::endl;
        return 0;
    }

    static void *hello_helper(void *context)
    {
        return ((C *)context)->hello();
    }
};
...
C c;
pthread_t t;
pthread_create(&t, NULL, &C::hello_helper, &c);

86voto

Jeremy Friesner Points 16684

Ma façon préférée de gérer un thread est d'encapsuler l'intérieur d'un objet C++. Voici un exemple:

class MyThreadClass
{
public:
   MyThreadClass() {/* empty */}
   virtual ~MyThreadClass() {/* empty */}

   /** Returns true if the thread was successfully started, false if there was an error starting the thread */
   bool StartInternalThread()
   {
      return (pthread_create(&_thread, NULL, InternalThreadEntryFunc, this) == 0);
   }

   /** Will not return until the internal thread has exited. */
   void WaitForInternalThreadToExit()
   {
      (void) pthread_join(_thread, NULL);
   }

protected:
   /** Implement this method in your subclass with the code you want your thread to run. */
   virtual void InternalThreadEntry() = 0;

private:
   static void * InternalThreadEntryFunc(void * This) {((MyThreadClass *)This)->InternalThreadEntry(); return NULL;}

   pthread_t _thread;
};

Pour l'utiliser, il vous suffit de créer une sous-classe de MyThreadClass avec le InternalThreadEntry() la méthode mise en œuvre pour contenir votre fil de la boucle d'événements. Vous auriez besoin de faire appel WaitForInternalThreadToExit() sur l'objet thread avant la suppression de l'objet thread, bien sûr (et de disposer d'un mécanisme pour s'assurer que le fil fait des sorties, sinon WaitForInternalThreadToExit() ne retournera jamais)

10voto

Jared Oberhaus Points 8877

Vous aurez à donner des pthread_create une fonction qui correspond à la signature c'est la recherche d'. Ce que vous êtes de passage ne fonctionne pas.

Vous pouvez mettre en œuvre quelle que soit la fonction statique vous aime pour cela, et il peut faire référence à une instance d' c et exécuter ce que vous voulez dans le fil. pthread_create est conçu pour faire, pas seulement un pointeur de fonction, mais un pointeur vers "contexte". Dans ce cas, vous venez de passer un pointeur vers une instance de c.

Par exemple:

static void* execute_print(void* ctx) {
    c* cptr = (c*)ctx;
    cptr->print();
    return NULL;
}


void func() {

    ...

    pthread_create(&t1, NULL, execute_print, &c[0]);

    ...
}

-1voto

EdH Points 630

J'imagine c'est b/c de se mutilé un peu en C++ b/c de votre envoi d'un pointeur C++, pas un C pointeur de fonction. Il y a une différence apparemment. Essayez de faire une

(void)(*p)(void) = ((void) *(void)) &c[0].print; //(check my syntax on that cast)

et ensuite l'envoyer p.

J'ai fait ce que vous faites avec une fonction membre aussi, mais je l'ai fait dans la classe qui l'utilise, et avec un statique de la fonction - qui, je pense, a fait la différence.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X