我的错误:
error: cannot convert 'MainWindow::producerThreadFunction' from type 'void* (MainWindow::)(void*)' to type 'void* (*)(void*)'
if (pthread_create (&producer, NULL, producerThreadFunction, NULL))
^
标题文件:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QApplication>
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <iostream>
#include <QDebug>
class MainWindow : public QMainWindow
{
Q_OBJECT
pthread_mutex_t mutexVariable = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t conditionVariable = PTHREAD_COND_INITIALIZER;
QList <int> queueLIFO;
public:
MainWindow(QWidget *parent = 0);
~MainWindow();
// This function is run by the thread `Producer`.
void *producerThreadFunction (void *arg);
// This function is run by the thread `Consumer`.
void *consumerThreadFunction (void *arg);
int start ();
};
#endif // MAINWINDOW_H
源文件:(发生错误的函数)
int MainWindow :: start()
{
pthread_t producer;
pthread_t consumer;
if (pthread_create (&producer, NULL, producerThreadFunction, NULL))
{
fprintf (stderr, "Error creating thread Producer\n");
return 1;
}
if (pthread_create (&consumer, NULL, consumerThreadFunction, NULL))
{
fprintf (stderr, "Error creating thread Consumer\n");
return 1;
}
if (pthread_join (producer, NULL))
{
fprintf (stderr, "Error joining thread Producer\n");
return 2;
}
if (pthread_join (consumer, NULL))
{
fprintf (stderr, "Error joining thread Consumer\n");
return 2;
}
return 0;
}
根据this thread,解决方案是使producerThreadFunction
静态。
为什么要将类的线程函数设置为静态才能在同一个类中访问?
该函数是该类的成员函数。为什么我不能直接访问它?
答案 0 :(得分:3)
pthread_create
需要一个函数指针,而不是指向成员函数的指针。这些是C ++中非常不同的类型,因为成员函数指针包含一个隐式this
指针。在实践中,静态成员函数等效于非成员函数,因此工作正常(N.B.根据标准,这在技术上并不正确 - 见下文)。
如果pthread
是C ++库,则可能需要std::function
(或者,在C ++ 11之前,boost::function
),它可以接受各种类似函数的对象;例如函数指针,成员函数指针或函子类。但是,由于pthread
是一个C库,因此您不得不编写静态函数并手动将this
指针作为参数传递。
您应该认真考虑使用std::thread
(或者,在C ++ 11之前,boost::thread
)而不是pthreads
。可以使用与pthreads
中可用的相同的同步原语,例如, std::condition_variable
。 std::thread
构造函数可以直接接受成员函数指针:
std::thread producer(&MainWindow::producerThreadFunction, this);
C和C ++可能使用不同的calling conventions。这意味着从C代码调用C ++函数不是安全的,除非它包含在extern "C"
block中。但是,正如this answer on StackOverflow指出的那样,C ++ 11 7.5 / 4&#34; Linkage规范&#34;表示:
在确定语言链接时忽略C语言链接 类成员的名称和类成员的函数类型 功能
因此,不保证按标准工作。唯一符合标准的选项是将代码放在非成员函数中,该函数在内部调用成员函数:
extern "C" {
void producerThreadFunctionWrapper(void *arg)
{
static_cast<MainWindow *>(arg)->producerThreadFunction();
}
} // extern "C"
// ...
pthread_create(&consumer, NULL, consumerThreadFunctionWrapper, this);
实际上,我从未遇到静态成员函数不使用C链接的体系结构/编译器。 question 33.2 in the C++FQA的答案幽默地提出了同样的观点:
但是,有一些关于StackOverflow(例如in 32 bit Visual Studio)的人被烧毁的报告。最安全的选择是使用关于static-members-as-callbacks问题:如果你的 实现对C使用不同的二进制调用约定 函数和C ++静态成员函数,调用支持和通知 他们的开发人员在工作中消耗改变思维的化学物质。
std::thread
或为回调编写extern "C"
包装。
答案 1 :(得分:1)
由于我们几乎完成了2015年,现在是时候抛弃C ++ 2003了。调用线程的最佳方法如下:
int MainWindow :: start()
{
std::thread producer(&MainWindow::producerThreadFunction, this);
...
看看它有多容易?而且根本不需要担心静态成员函数!