gpt4 book ai didi

c++ - 为什么一个类的线程函数要静态化才能在同一个类中访问?

转载 作者:行者123 更新时间:2023-11-30 01:45:46 24 4
gpt4 key购买 nike

我的错误:

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 静态。

为什么一个类的线程函数要静态化才能在同一个类中访问?

那个函数是那个类的成员函数。为什么不能直接访问?

最佳答案

pthread_create 需要一个函数指针,而不是指向成员函数的指针。这些在 C++ 中是非常不同的类型,因为成员函数指针包含一个隐式 this 指针。实际上,静态成员函数等同于非成员函数,因此可以正常工作(注意,根据标准,这在技术上是不正确的 - 见下文)。

如果 pthread 是一个 C++ 库,它可能需要一个 std::function(或者,在 C++11 之前,一个 boost::function ) 可以接受各种类似函数的对象;例如函数指针、成员函数指针或仿函数类。但是,由于 pthread 是一个 C 库,因此您不得不编写静态函数并手动将 this 指针作为参数传递。

你应该认真考虑使用 std::thread(或者,在 C++11 之前,boost::thread)而不是 pthreads .与 pthreads 中可用的同步原语相同,例如std::condition_variablestd::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“链接规范”说:

A C language linkage is ignored in determining the language linkage of the names of class members and the function type of class member functions.

因此,不能保证按标准工作。唯一符合标准的选项是将代码放在非成员函数中,该函数在内部调用成员函数:

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的答案幽默地表达了同样的观点:

Regarding the static-members-as-callbacks issue: if your implementation uses different binary calling conventions for C functions and C++ static member functions, call the support and inform them that their developers consume mind-altering chemicals at work.

但请注意,StackOverflow 上有一些报告(例如 in 32 bit Visual Studio)有人因此而被烧毁。最安全的选择是使用 std::thread 或为您的回调编写一个 extern "C" 包装器。

关于c++ - 为什么一个类的线程函数要静态化才能在同一个类中访问?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34036762/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com