Pergunta

eu quero fazer este simples pedaço de código de trabalho.

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

Estou no Windows, usando vs. Qualquer ajuda será muito appriciated.

Foi útil?

Solução

Pessoalmente, eu não iria considerar passando em um ponteiro de função que você está tentando fazer como muito C ++ como. Isso é codificação C em C ++

Em vez disso, eu embrulhar aquela coisa em uma classe. A grande vantagem existe você pode simplesmente substituir a classe de ter no entanto muitos membros que você quer, ao invés de ter que realizar truques de fundição Greazy para chegar a seus parâmetros de cada vez.

O código é um pouco prolixo, assim que eu empurrei-o até o fim. Mas o que lhe permite fazer é algo como isto:

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

Aqui está um código de exemplo exerpted de uma de nossas classes que faz isso:

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

... e no 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());

}

Outras dicas

CreateThread quer 2 argumentos: ponteiro para a função a ser executada como um fio, e um argumento DWORD que será dado para o segmento. sua função spawnThread () só tem um argumento (threadName); você pensar tem 2 argumentos por causa do "i", mas que é realmente parte da definição do tipo "threadName". (Você poderia muito bem deixar de fora o "i";. Ou seja, você não precisa nomear os argumentos para "threadName")

De qualquer forma, já que você precisa de 2 argumentos, redefine spawnThread:

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

Observe que eu não fiz nome o argumento int ao threadEntryPoint; é suficiente para dizer ao compilador que a função deve ter um único argumento int.

e chamá-lo:

   spawnThread(printSome, 155);

De qualquer forma, rápido e sujo, isso vai fazer o que quiser.

hth.

Reilly.

Você não pode passar informações de parâmetro em um ponteiro de função; ele deve ser passado separadamente. Isso é exatamente porque a função CreateThread fornece um parâmetro * vazio que pode apontar para o que quiser.

Além disso, você deve _beginthread vez de CreateThread para aplicações C ++.

Finalmente, o programa é mais do que provável para terminar antes que o segmento já é executado. Portanto, você deve inserir um loop indefinido ou usar uma chamada de API que esperar para o segmento ao fim.

A seguir é uma versão de trabalho usando WaitForSingleObject para bloco até da conclusão do fio.

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

Aqui é um C ++ / forma muito mais orientada a objeto de manipulação esta mesma situação:

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

Como muitas pessoas já mencionado aqui, você não pode passar um ponteiro de função eo argumento deve ser chamado com em um parâmetro.

A sua linha

    spawnThread(printSome(155));

"deveria" (em DWIM mundo) média "Invoke printSome em um segmento separado com o argumento 155". No entanto, não é como C ++ entende. C ++ vê "Passe o resultado de printSome invocado em 155 como um parâmetro para spawnThread". Em outras palavras, a seqüência de etapas é a seguinte:

  • chamada prinotSome com 155 como argumento. Armazená-lo na memória temporária.
  • chamar spawnThread com o conteúdo da memória temporária como seu argumento.

A fim de fazer o que você realmente quer dizer, você tem que humor C ++ e argumento separado da função. Como fazê-lo já é explicado em outras respostas. A curto do que é:

callOnOtherThreadWithArgument (função, número inteiro);

Você pode ler como fazer isso aqui: http://www.newty.de/ FPT / fpt.html

2.6 Como passar um ponteiro função como um argumento?

Você pode passar um ponteiro de função como um função está chamando argumento. Você precisa este, por exemplo, se você quer passar um ponteiro para uma função de retorno. o seguinte mostra o código como passar uma ponteiro para uma função que retorna uma int e leva uma bóia e duas caractere:

//------------------------------------------------------------------------------------
// 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);
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top