jerrypy
jerrypy

Reputation: 139

Create a new thread using C in Qt4.8

I'm developing a simple instant-messaging software on Ubuntu 12.10, it's client requires GUI.
In the main window of the client, i need to create a thread to keep listening messages received from the server.


Here is the error message:

main.cpp:-1: In function 'int main(int, char**)':
main.cpp:27: error: invalid conversion from 'void*' to 'void* (*)(void*)' [-fpermissive]

 /usr/include/pthread.h:225: error:   initializing argument 3 of 'int pthread_create(pthread_t*, const pthread_attr_t*, void* (*)(void*), void*)' [-fpermissive]

In the maininterface.h:

Class MainInterface: public QWidget
{
public:
    explicit MainInterface(QWidget *parent = 0);
    ~MainInterface();
    void* ServerMSGWatch(void *threadArgs=NULL); // function run in the new thread

};

It's definition in maininterface.cpp is:

void* MainInterface::ServerMSGWatch(void *threadArgs)
{
    pthread_detach(pthread_self());
    char arrServerMSGRecv[SERVER_MSG_MAX_SIZE + 1];
    while(1){
        recv(Login::sockClnt, arrServerMSGRecv, SERVER_MSG_MAX_SIZE+1, 0);
        Handle_Server_MSG(arrServerMSGRecv); 
        memset(arrServerMSGRecv, 0, SERVER_MSG_MAX_SIZE+1);
    }
    return NULL;
}

in main.cpp:

MainInterface mWindow;
mWindow.show();
pthread_t pthreadID;
pthread_create(&pthreadID, NULL, mWindow.ServerMSGWatch(), NULL); 

and in this question, i figured out that maybe there's something wrong with using a C++ compiler to compile c code.

so i tried to add a 'c_pthread.h':

#ifndef C_PTHREAD_H
#define C_PTHREAD_H

#ifdef  __cplusplus

extern "C" {

#endif

void* ServerMSGWatch(void *threadArgs=NULL);
void Handle_Server_MSG(char *arrServerMSGRecv);

#ifdef  __cplusplus

}
#endif
#endif // C_PTHREAD_H

and c_pthread.cpp:

void* ServerMSGWatch(void *threadArgs=NULL)
{
     //definition
}

void Handle_Server_MSG(char *arrServerMSGRecv)
{
    //definition
}

then invoke it in main.cpp:

#include "c_pthread.h"
pthread_t pthreadID;
pthread_create(&pthreadID, NULL, ServerMSGWatch(), NULL); 

but i still got the same error.


PS: sorry about some malapropisms.

Upvotes: 1

Views: 303

Answers (4)

Mike Seymour
Mike Seymour

Reputation: 254661

In C++11, there's no need to muck around with low-level system libraries:

std::thread thread([&]{mWindow.ServerMSGWatch();});

If you're stuck with a historic version of C++ then, since you say you're using Qt, you might consider its thread class QThread.

If you're stuck with pthreads then, being a C API, it knows nothing about member functions, so you'll need a non-member, or static member function. (Strictly speaking, you should only use a non-member function declared extern "C", but in practice C++ functions will work on any sensible implementation).

So you'll need a wrapper function to call the member function:

void * CallServerMSGWatch(void * p) {
    return static_cast<MainInterface*>(p)->ServerMSGWatch();
}

and tell pthread_create to pass a suitable pointer through to this:

pthread_create(&pthreadID, NULL, CallServerMSGWatch, &mWindow); 

Upvotes: 1

Some programmer dude
Some programmer dude

Reputation: 409404

You have two problems: The first is that you call the function instead of passing it. The other is more subtle, and is that you can't use a non-static class member function as a thread function.

The reason for the last problem is because non-static member function have a hidden first argument that is the this pointer.

In this case you can solve it by adding a static member function, and pass a pointer to the object as argument to the thread function. Then the static function calls the actual function in the object:

class MainInterface: public QWidget
{
public:
    ...

    static void* StaticServerMSGWatch(void* arg)
    {
        reinterpret_cast<MainInterface*>(arg)->ServerMSGWatch();
        return nullptr;
    }

    void ServerMSGWatch(); // function run in the new thread
};

...

pthread_create(&pthreadID, NULL, &MainInterface::StaticServerMSGWatch, &mWindow);

If you have a C++11 capable compiler and library, you could use std::thread instead:

std::thread myThread(&MainInterface::ServerMSGWatch, &mWindow);

As you see, you no longer need the static member function.

Upvotes: 5

rubenvb
rubenvb

Reputation: 76720

You're using Qt, so I strongly suggest using QThread. This will guarantee compatibility and the interop with the rest of your program will be better.

That being said, you need to pass a function pointer to pthread_create, and a member function pointer is not a function pointer: either make it static or make it a freestanding function.

Upvotes: 4

Martin James
Martin James

Reputation: 24897

mWindow.ServerMSGWatch() is a function call.

mWindow.ServerMSGWatch is a function pointer.

Upvotes: 0

Related Questions