Question

Je veux faire ce simple travail de code.

#include <iostream>
#include <windows.h>


    void printSome (int i)
    {
        std::cout << i << std::endl;
    }

    void spawnThread (void (*threadName)(int i))
    {
        CreateThread 
            (
                0,      // default security attributes
                0,          // use default stack size 
                (LPTHREAD_START_ROUTINE)threadName,  // thread function name
                (LPVOID)i,          // argument to thread function 
                0,          // use default creation flags 
                0       // returns the thread identifier 
            );  
    }

    int main ()
    {
        spawnThread(printSome(155));
    }

Je suis sur Windows, j'utilise vs toute aide sera grandement appréciée.

Était-ce utile?

La solution

Personnellement, je n’envisagerais pas de passer un pointeur de fonction comme vous essayez de faire comme C ++. C'est coder C en C ++

Au lieu de cela, je vais envelopper cette chose dans une classe. Le gros avantage est que vous pouvez simplement remplacer la classe par le nombre de membres que vous voulez, plutôt que de devoir effectuer de très astuces de casting pour obtenir vos paramètres à chaque fois.

Le code est un peu long, alors je l'ai poussé jusqu'au bout. Mais cela vous permet de faire quelque chose comme ceci:

   class print_some : public basic_thread {
    private:
       int i;
    public:     
       print_some (int i) : i(i) {};
       action_callback () {
          std::cout << i << std::endl;
       }
    }
    int main () {
       print_some printer (155);
    }

Voici un exemple de code extrait d'une de nos classes:

class basic_thread : 
{
public:
   basic_thread();
protected:
   unsigned long m_ThreadId;

   virtual void action_callback () {};

   // Internal routine used to bridge between OS callback format and 
   // action_callback. *Must* be static for the OS.
   static unsigned long __stdcall self_calling_callback (void *parameter);
}

... et dans le fichier .cpp:

unsigned long __stdcall basic_thread::self_calling_callback (void *parameter) {
   if (parameter) {
      basic_thread * thread = reinterpret_cast<basic_thread *>(parameter);
      thread->action_callback();
   }
   return 0; // The value returned only matters if someone starts calling GetExitCodeThread
             // to retrieve it.
}

basic_thread::basic_thread () {
   // Start thread.
   m_Handle = CreateThread(NULL,
                           0,
                           self_calling_callback,
                           (PVOID)this,
                           0,
                           &m_ThreadId );
   if( !IsHandleValid() )
      throw StartException("CreateThread() failed", GetLastError());

}

Autres conseils

CreateThread souhaite 2 arguments: un pointeur sur la fonction à exécuter en tant que thread et un argument DWORD qui sera donné au thread. votre fonction spawnThread () a seulement 1 argument (threadName); vous pensez qu'il a 2 arguments à cause du "i", mais cela fait vraiment partie de la définition du "threadName" type. (vous pouvez également omettre le "i"; c’est-à-dire que vous n’avez pas besoin de nommer les arguments de "threadName".)

de toute façon, étant donné que vous avez besoin de 2 arguments, redéfinissez spawnThread:

   void spawnThread(void (*threadEntryPoint)(int), int argument)
   {
      CreateThread(0,0,
                   (LPTHREAD_START_ROUTINE)threadEntryPoint,
                   (LPVOID)argument,
                   0,0);
   }

remarquez que je n'ai pas nommé l'argument int de threadEntryPoint; il suffit de dire au compilateur que la fonction doit avoir un seul argument int.

et appelez-le:

   spawnThread(printSome, 155);

de toute façon, rapide et sale, cela fera ce que vous voulez.

hth.

reilly.

Vous ne pouvez pas transmettre d'informations de paramètre dans un pointeur de fonction; il doit être passé séparément. C’est précisément pourquoi la fonction CreateThread fournit un paramètre void * qui peut pointer vers ce que vous voulez.

De plus, vous devez utiliser _beginthread au lieu de CreateThread . pour les applications C ++.

Enfin, il est plus que probable que votre programme se termine avant que le thread ne soit exécuté. Par conséquent, vous devez soit entrer une boucle indéfinie, soit utiliser un appel API pour attendre la fin du thread.

Ce qui suit est une version de travail utilisant WaitForSingleObject pour bloquer jusqu'à le fil se termine.

#include <iostream>
#include <process.h>
#include <windows.h>

void
printSome(int i)
{
    std::cout << i << std::endl;
}

HANDLE
spawnThread(void (*threadName)(int), int i)
{
    return (HANDLE) _beginthread((void (*)(void*)) threadName, 0, (LPVOID) i);      
}

int
main(int argc, char *argv[])
{
    HANDLE threadHandle;

    threadHandle = spawnThread(printSome, 155);
    WaitForSingleObject(threadHandle, INFINITE);

    return 0;
}

Voici une manière beaucoup plus orientée objet / C ++ de gérer cette même situation:

#include <iostream>
#include <process.h>
#include <windows.h>

class Thread {
    static void proxy(void *arg) { (*(reinterpret_cast<Thread *> (arg)))(); }
    HANDLE thread_;

public:
    virtual ~Thread() {}
    virtual void operator()() = 0;  
    void start() { thread_ = (HANDLE) _beginthread(Thread::proxy, 0, this);}    
    void waitForExit() { WaitForSingleObject(thread_, INFINITE); }
};

class Printer : public Thread {
    int i_;

public:
    Printer(int i) : i_(i) {}
    void operator()() { std::cout << i_ << std::endl; }
};

int
main(int argc, char *argv[])
{
    Printer p(155);

    p.start();
    p.waitForExit();

    return 0;
}

Comme beaucoup de personnes ont déjà été mentionnées ici, vous ne pouvez pas transmettre un pointeur de fonction et l'argument avec lequel il doit être appelé dans un paramètre.

Votre ligne

    spawnThread(printSome(155));

" devrait " (dans le monde DWIM) signifie "Invoke printSome sur un thread séparé avec l’argument 155". Cependant, ce n'est pas comme cela que le C ++ le comprend. C ++ voit "Transmettre le résultat de printSome invoqué sur 155 en tant que paramètre pour spawnThread". En d'autres termes, la séquence des étapes est la suivante:

  • appelez prinotSome avec 155 comme argument. Stockez-le en mémoire temporaire.
  • appelez spawnThread avec le contenu de la mémoire temporaire comme argument.

Pour faire ce que vous voulez vraiment dire, vous devez vous amuser en C ++ et séparer les arguments des fonctions. Comment le faire est déjà expliqué dans d'autres réponses. En bref:

callOnOtherThreadWithArgument (fonction, entier);

Vous pouvez lire comment faire cela ici: http://www.newty.de/ fpt / fpt.html

  

2.6 Comment passer un pointeur de fonction en tant qu’argument?

     

Vous pouvez passer un pointeur de fonction en tant que   argument d'appel de la fonction. Vous avez besoin   cela par exemple si vous voulez passer un   pointeur sur une fonction de rappel. le   Le code suivant montre comment passer un   pointeur sur une fonction qui retourne un   int et prend un float et deux caractères:

//------------------------------------------------------------------------------------
// 2.6 How to Pass a Function Pointer

// <pt2Func> is a pointer to a function which returns an int and takes a float and two char
void PassPtr(int (*pt2Func)(float, char, char))
{
   int result = (*pt2Func)(12, 'a', 'b');     // call using function pointer
   cout << result << endl;
}

// execute example code - 'DoIt' is a suitable function like defined above in 2.1-4
void Pass_A_Function_Pointer()
{
   cout << endl << "Executing 'Pass_A_Function_Pointer'" << endl;
   PassPtr(&DoIt);
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top