开发者

I am new to threads, What does this compile error mean?

Using 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
    }
}

...

Compile Error: TCPClient.cpp:109: error: argument of type ‘void (ClientHandler::)(void*)’ does not match ‘void* (*)(void*)’

I can't figure out whats wrong. Thanks in advance.


A pointer to a member function is different from a global function with the same signature since the member function needs an additional object on which it operates. Therefore pointers to these two types of functions are not compatible.

In this case this means that you cannot pass a member function pointer to pthread_create but only a pointer to a non-member (or static) function. A work around for this problem is to use the forth parameter of pthread_create to pass a pointer to a object to a global function which then calls the method of the passed object:

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


It's nothing to do with threads, it's a normal C++ error, you're just passing an incompatible type of function pointer.

A function pointer is not the same as a member instance function pointer, even if their signature is the same; this is because there is an implicit reference to *this passed. You can't avoid this.


As pthread_create takes a free function, create a static function(is a free function) inside 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);

That works because Callback is free function


YoLinux has a nice pthread tutorial that my help you in learning about threads.


As others have already said, the problem is that the signatures between the functions are different. Class member functions always have a "secret" extra parameter, the this pointer. So you can never pass a member function where a global function is expected. You can hack around this either with libraries such as Boost.Bind, or by making the function a static member of the class.

But the simplest, and most elegant solution is to use a different threading API.

Boost.Thread is a very nice threading library for C++ (pthreads is designed for C, and that's why it doesnt play well with C++ features such as class methods).

I'd recommend using that.

Your code could be rewritten as something like this:

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*/));


You're passing a member function instead of a global, normal, one.

Just define:

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜