我是线程的新手,这个编译错误意味着什么?

时间:2009-11-29 14:42:30

标签: c++ multithreading

使用C ++。

pthread_t threads[STORAGE]; // 0-99

...

void run()

Error>>>    int status = pthread_create(&threads[0], NULL, updateMessages, (void *) NULL);
if (status != 0)
{
    printf("pthread_create returned error code %d\n", status);
    exit(-1);
}

...

void ClientHandler::updateMessages(void *)
{
    string reqUpdate = "91"; // Request for update
    string recvMSG;
    while (true)
    {
        sleep(5);
        sending(sock,reqUpdate); // send
        recvMSG = receiving(sock); // receive
        QString output(recvMSG);
        emit signal_chat(output, 0);    // Print message to text box
    }
}

...

编译错误: TCPClient.cpp:109: error: argument of type ‘void (ClientHandler::)(void*)’ does not match ‘void* (*)(void*)’

我无法弄清楚什么是错的。 提前谢谢。

6 个答案:

答案 0 :(得分:7)

指向成员函数的指针与具有相同签名的全局函数不同,因为成员函数需要一个其操作的附加对象。因此,指向这两种函数的指针不兼容。

在这种情况下,这意味着您不能将成员函数指针传递给pthread_create,而只能传递指向非成员(或静态)函数的指针。解决此问题的方法是使用pthread_create的第四个参数将指向对象的指针传递给全局函数,然后全局函数调用传递的对象的方法:

class ClientHandler {
public:
   void updateMessages();
   void run();
};

// Global function that will be the threads main function.
// It expects a pointer to a ClientHandler object.
extern "C"
void *CH_updateMessages(void *ch) {
   // Call "real" main function
   reinterpret_cast<ClientHandler*>(ch)->updateMessages();
   return 0;
}

void ClientHandler::run() {
  // Start thread and pass pointer to the current object
  int status = pthread_create(&threads[0], NULL, CH_updateMessages, (void*)this);
  ...
}

答案 1 :(得分:6)

它与线程无关,这是一个正常的C ++错误,你只是传递一个不兼容的函数指针类型。

函数指针与成员实例函数指针不同,即使它们的签名相同;这是因为有一个隐含的引用* this传递。你无法避免这种情况。

答案 2 :(得分:0)

当pthread_create采用自由函数时,在ClientHandler中创建一个静态函数(是一个自由函数)

static void Callback(void * this_pointer,int other_arg) {
    ClientHandler* self = static_cast< ClientHandler*>(this_pointer);
    self-> updateMessages(other_arg);
}
and call pthread_create as follows

pthread_create(&threads[0], NULL, &ClientHandler::Callback, (void *) pointer_to_ClientHandler,int other_arg);

这有效,因为Callback是免费功能

答案 3 :(得分:0)

YoLinux有一个很好的pthread教程,我帮助你学习线程。

答案 4 :(得分:0)

正如其他人已经说过的那样,问题是功能之间的签名是不同的。类成员函数始终具有“秘密”额外参数this指针。因此,您永远不能传递期望全局函数的成员函数。您可以使用诸如Boost.Bind之类的库来解决这个问题,或者将该函数作为该类的静态成员。

但最简单,最优雅的解决方案是使用不同的线程API。

Boost.Thread是一个非常好的C ++线程库(pthreads是为C设计的,这就是为什么它不能很好地运用类方法等C ++特性)。

我建议使用它。

您的代码可以重写为:

class ClientHandler {
public:
  ClientHandler(/* All the parameters you want to pass to the thread. Unlike pthreads you have complete type safety and can pass as many parameters to this constructor as you like */){...}
  void operator()() // boost.thread calls operator() to run the thread, with no parameters. (Since all parameters were passed in the constructor and saved as member variables
  {
    string reqUpdate = "91"; // Request for update
    string recvMSG;
    while (true)
    {
        sleep(5);
        sending(sock,reqUpdate); // send
        recvMSG = receiving(sock); // receive
        QString output(recvMSG);
        emit signal_chat(output, 0);    // Print message to text box
    }
  }
  // whatever arguments you want to pass to the thread can be stored here as member variables
};


boost::threead_group gr; // can store all your threads here, rather than being limited to your fixed-size array

gr.create_thread(ClientHandler(/* construct a ClientHandler object with the parameters you like*/));

答案 5 :(得分:-1)

您传递的是成员函数而不是全局的普通函数。

只需定义:

void updateMessages(void *) {
static ClientHandler c;
// use c..
}