使用Qt4.8中的C创建一个新线程

Create a new thread using C in Qt4.8

本文关键字:一个 Qt4 新线程 线程 中的 创建 使用      更新时间:2023-10-16

我正在Ubuntu 12.10上开发一个简单的即时消息软件,它的客户端需要GUI
在客户端的主窗口中,我需要创建一个线程来保持侦听从服务器接收的消息。


这是错误消息:

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]

maininterface.h:中

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

它在maininterface.cpp中的定义是:

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

main.cpp:中

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

在这个问题中,我发现使用C++编译器编译C代码可能有问题。

所以我尝试添加一个"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

c_pthread.cpp:

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

然后在main.cpp:中调用它

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

但我还是犯了同样的错误。


附言:很抱歉有些口误。

您有两个问题:第一个是您调用函数而不是传递它。另一个更微妙的问题是,您不能将非静态类成员函数用作线程函数。

最后一个问题的原因是非静态成员函数有一个隐藏的第一个参数,即this指针。

在这种情况下,您可以通过添加static成员函数来解决它,并将指向对象的指针作为参数传递给线程函数。然后静态函数调用对象中的实际函数:

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

如果你有一个支持C++11的编译器和库,你可以使用std::thread来代替:

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

正如您所看到的,您不再需要静态成员函数。

您使用的是Qt,所以我强烈建议使用QThread。这将保证兼容性,并且与程序其他部分的互操作将更好。

也就是说,您需要将一个函数指针传递给pthread_create,而成员函数指针不是函数指针:要么将其设为static,要么将其设置为独立函数。

在C++11中,不需要摆弄低级系统库:

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

如果你一直使用C++的历史版本,那么既然你说你在使用Qt,你可能会考虑它的线程类QThread

如果您一直使用pthreads,那么作为一个C API,它对成员函数一无所知,所以您需要一个非成员或静态成员函数。(严格地说,您应该只使用声明为extern "C"的非成员函数,但在实践中,C++函数可以用于任何合理的实现)。

因此,您需要一个包装函数来调用成员函数:

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

并告诉pthread_create将一个合适的指针传递给这个:

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

mWindow.ServerMSGWatch()是一个函数调用。

mWindow.ServerMSGWatch是一个函数指针。