Frage

Ich möchte dieses einfache Stück Code tun.

#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));
    }

ich bin auf Windows, mit vs. Jede Hilfe sehr appriciated wird.

War es hilfreich?

Lösung

Persönlich würde ich nicht die Ansicht in einem Funktionszeiger vorbei wie Sie versuchen, wie sehr C zu tun ++ wie. Das ist Codierung C in C ++

Stattdessen würde ich das Ding in einer Klasse wickeln. Der große Vorteil besteht kann man einfach die Klasse überschreibt, aber viele Mitglieder haben, die Sie wollen, anstatt Greazy Casting Tricks ausführen zu Ihren Parametern jedes Mal zu bekommen.

Der Code ist ein wenig langatmig, so schob ich es bis zum Ende. Aber was können Sie damit tun, ist so etwas wie folgt aus:

   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);
    }

Hier einige exerpted Beispielcode aus einer unserer Klassen, das dies tut:

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);
}

... und in der 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());

}

Andere Tipps

Create will 2 Argument: Zeiger auf die Funktion als ein Gewinde, und ein DWORD Argument auszuführen, die auf den Faden gegeben werden. Ihre spawnThread () Funktion hat nur 1 Argument (threadName); Sie denken es hat 2 args wegen der „i“, aber das ist wirklich Teil der Definition des „threadName“ -Typ. (Man könnte genauso gut auslassen die „i“;. Das heißt, Sie brauchen nicht die Argumente Namen „threadName“)

Wie auch immer, da Sie zwei Argumente NEED, neu definieren spawnThread:

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

Hinweis, dass ich nicht name das int Argument der threadEntryPoint; es reicht aus, um den Compiler zu sagen, dass die Funktion ein einzelnes int Argument hat.

und nennt es:

   spawnThread(printSome, 155);

Wie auch immer, schnell und schmutzig, dies tun, was Sie wollen.

hth.

Reilly.

Sie können keine Parameterinformationen in einem Funktionszeiger übergeben; es muss separat übergeben werden. Das ist genau, warum die Funktion Createthread einen void * Parameter bereitstellt, die darauf hinweisen können, was Sie wollen.

Darüber hinaus sollten Sie verwenden _beginthread statt Create für C ++ Anwendungen.

Schließlich Ihr Programm ist mehr als wahrscheinlich zu beenden, bevor der Faden immer läuft. Daher müssen Sie entweder eine unbestimmte Schleife eingeben oder einen API-Aufruf verwenden, um zu warten, bis der Thread zu beenden.

Das folgende ist eine Arbeitsversion mit WaitForSingleObject zu blockieren, bis der Thread abgeschlossen ist.

#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;
}

Hier ist eine viel C ++ / objektorientierte Art und Weise dieselbe Situation der Handhabung:

#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;
}

Wie viele Menschen hier bereits erwähnt, können Sie nicht einen Funktionszeiger und das Argument übergeben Sie sie mit einem Parameter aufgerufen werden sollen.

Ihre Zeile

    spawnThread(printSome(155));

"sollte" (in DWIM Welt) bedeuten "Invoke printSome auf einem separaten Thread mit dem Argument 155". Allerdings ist es nicht, wie C ++ versteht. C ++ sieht „das Ergebnis von Pass printSome auf 155 als Parameter an spawnThread aufgerufen“. Mit anderen Worten, ist die Reihenfolge der Schritte:

  • rufen prinotSome mit 155 als Argument. Bewahren Sie es im temporären Speicher.
  • ruft spawnThread mit dem Inhalt des temporären Speichers als Argument.

Um das zu tun, was Sie wirklich bedeuten, müssen Sie Humor C ++ und separates Argument von der Funktion. Wie es zu tun ist bereits in anderen Antworten erklärt. Die kurze davon ist:

callOnOtherThreadWithArgument (Funktion, integer);

lesen Sie, wie Sie das tun, hier: http://www.newty.de/ fpt / fpt.html

  

2.6 Wie ein Funktionszeiger als Argument übergeben?

     

Sie können einen Funktionszeiger als ein Pass   Funktion der anrufenden Argument. Du brauchst   dies zum Beispiel, wenn Sie wollen eine passieren   Zeiger auf eine Rückruffunktion. Das   folgende Code zeigt, wie ein passieren   Zeiger auf eine Funktion, die eine zurück   int und nimmt einen Schwimmer und zwei Zeichen:

//------------------------------------------------------------------------------------
// 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);
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top