我正在尝试使用以下代码在c ++中创建一个线程:
pthread_t mythread;
void* f (void*) = MyClass::myfunction;
pthread_create(&mythread, NULL, &f, NULL);
它不起作用。知道什么是错的吗?
myfunction的类型为:
void* MyClass::myfunction(void* argv);
返回的错误是:
error: declaration of ‘void* Class::f(void*)’ has ‘extern’ and is initialized
error: invalid pure specifier (only ‘= 0’ is allowed) before ‘::’ token
error: function ‘void* Class::f(void*)’ is initialized like a variable
答案 0 :(得分:6)
您将f
声明为函数而不是函数指针。它应该是:
void* (*f) (void*) = &MyClass::myfunction;
^^^^
pthread_create(&mythread, NULL, f, NULL);
^ no & since it's already a pointer
这也只有在myfunction
是静态的情况下才有效,因为你无法将指向成员的函数转换为指向函数的指针。
如果您确实需要线程在特定对象上执行非静态成员函数,那么一种方法是编写一个静态包装器,将该对象作为参数:
class MyClass {
public:
void start_thread() {
// Pass "this" to the thread we're creating
pthread_create(&mythread, NULL, &MyClass::thread_entry, this);
}
private:
static void * thread_entry(void * object) {
// Call the member function on the object passed to the thread
return static_cast<MyClass*>(object)->thread();
}
void * thread() {
// do the interesting stuff, with access to the member variables
}
};
当然,现在有一个标准的线程库,不再需要这种舞蹈:
std::thread thread(&MyClass::thread, this);
答案 1 :(得分:2)
Pthreads需要函数指针,对于类,只能使用函数指针指向静态方法。
如果您想在某个特定对象上调用某个类的特定方法,则需要两个独立的数据部分:
这两个连接在一起的可以非正式地称为委托。
PThreads是一个C库,为了与之互操作,您需要一些解决方法:
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine)(void*),
void *arg);
我们要将类方法包装在一个静态类方法中,以便能够将它作为参数start_routine
传递,我们将把指针传递给对象本身{{1} }。
参见代码:
arg
此类解决方法允许您使用struct Foo {
// wrapper method
static void* threadStartingPoint(void* obj) {
return ((Foo)obj)->threadFunc();
}
// your target method itself
void* threadFunc() {
// this is where you do your logic
}
}
。
请注意,如果您足够幸运拥有支持pthread_create(thread, attr, Foo::threadStartingPoint, someObject)
的现代编译器,则可以使用它而不是pthreads并使代码更简单 - 您只需要创建一个std::thread
对象并且将它传递给std::function
的构造函数。
答案 2 :(得分:1)
你简单不能做你想做的事 - 一个成员函数(除非它是静态的)需要一个被调用的对象 - 也就是启动线程的进程不能只调用MyClass :: f ()因为它需要调用something.f() - 而且它不知道是什么东西。
通常可以通过定义一个静态成员函数来解决这个问题,该函数将对象作为参数,然后在该对象上调用成员函数。