简体   繁体   English

使用pthreads时如何在C ++中将方法指针作为函数参数传递

[英]How can I pass method pointer as a function parameter in C++ while using pthreads

I have a question related with C++ and threads. 我有一个与C ++和线程有关的问题。 I am more familiar with Java than C++ and this error is confusing me. 我对Java的了解比对C ++的了解还要多,这个错误使我感到困惑。

Imagine that in xh file I have a class such as: 想象一下,在xh文件中,我有一个诸如以下的类:

class A{

    public A();

    public virtual void* func(void*);

    public virtual void func2();

    public virtual void func3();

};

In x.cpp file I want to do that: 在x.cpp文件中,我想这样做:

void* A::func(void*) {

    while(....)
        func2();

    return NULL;
}

void A::func2() {

    ...some stuff there...

}

void A::func3() {

    pthread_t t1;

    pthread_create(&t1, NULL, &A::func, NULL);

    void* result;

    pthread_join(t1,&result);

    ...some other stuff...

}

The problem is it hangs with the following error: 问题是它因以下错误而挂起:

"error: ISO C++ forbids taking the address of an unqualified or parenthesized non-static member function to form a pointer to member function." “错误:ISO C ++禁止使用不合格或带括号的非静态成员函数的地址形成指向成员函数的指针。”

What should I do to fix this? 我应该怎么做才能解决这个问题?

Thanks. 谢谢。

This is a lousy error message, but fundamentally what it's trying to tell you is that you can't form a function pointer from an instance method (I'm not sure what Java's terminology here is). 这是一个糟糕的错误消息,但从根本上讲,它试图告诉您的是您不能从实例方法中形成函数指针(我不确定这里的Java术语是什么)。 This is because to call an instance method you need both the address of the actual code and the address of an object to be this , and a regular function pointer only stores the former. 这是因为要调用实例方法,您既需要实际代码的地址,也需要对象的地址为this ,而常规函数指针仅存储前者。

What you need here is a static wrapper method which matches pthread_create 's expectations of the thread start routine. 您需要的是一个static包装器方法,该方法可以匹配pthread_create对线程启动例程的期望。 You pass this as the fourth argument to pthread_create , and the wrapper converts its argument back to an object pointer and invokes func . this作为第四个参数传递给pthread_create ,包装器将其参数转换回对象指针并调用func This type of wrapper is commonly known as a " thunk ", since it adapts one calling convention to another. 这种类型的包装程序通常称为“ thunk ”,因为它可以使一种调用约定适应另一种调用约定。

class A {
    // ...
    static void* thread_start_thunk(void* self);
};

void*
A::thread_start_thunk(void* self)
{
    return static_cast<A*>(self)->func();
}

// ...

void
A::func3()
{
    // ....
    pthread_create(&t1, 0, &A::thread_start_thunk, static_cast<void*>(this));
    // ...
}

The casts are unavoidable. 演员阵容是不可避免的。

You can not just pass a pointer to a method to the thread. 您不能只将指向方法的指针传递给线程。 That method-pointer alone would not mean anything, because it does not know which instance it belongs to. 该方法指针本身就没有任何意义,因为它不知道它属于哪个实例。 If you need to call an instance method in a different thread, add a private static method to the class and pass it's address to the thread, along with a pointer to the instance as an argument. 如果您需要在其他线程中调用实例方法,请向该类添加一个私有静态方法,并将其地址与该实例的指针一起作为参数传递给线程。

That static method could look somewhat like this: 该静态方法可能看起来像这样:

class A
{
    public: virtual void threadMethod();

    public:
        static void staticThreadMethod(void* instanceObj)
        {
            ((A*)instanceObj)->threadMethod();
        }
};

I did not test that code and it obviously does not check for errors, but this is how I usually do it. 我没有测试该代码,并且显然也没有检查错误,但这就是我通常这样做的方式。

use one of: 使用以下之一:

  • boost::thread boost ::线程
  • C++11 C ++ 11
  • some other C++ library threads (a plenty of them) 其他一些C ++库线程(很多)
  • add a static method to your class, then pass its address to pthread_create w/ user provided void* to pair of your class instance (pointer/ref) and class::*method you want to call. 在您的类中添加静态方法,然后将其地址传递给pthread_create w /用户提供的void*到您的类实例对(指针/ ref)和要调用的class :: *方法。 then in static function just call desired method using instance and method address obtained from parameter 然后在静态函数中,只需使用从参数获取的实例和方法地址来调用所需的方法

In pthread_create(&t1, NULL, &func, NULL); pthread_create(&t1, NULL, &func, NULL); you try to take the address of a member function. 您尝试获取成员函数的地址。 There are two issues with that 有两个问题

  1. The correct form is 正确的形式是

    &A::func

    this is what the compiler tries to tell you. 这就是编译器试图告诉您的。

  2. pthread_create wants a pointer to function, not a pointer to a non-static member function. pthread_create想要一个函数指针, 而不是一个非静态成员函数指针。 What you can do instead is, creating a static member function and passing the address of this static member function as an argument to pthread_create . 您可以做的是,创建一个静态成员函数并将该静态成员函数的地址作为参数传递给pthread_create

Example: 例:

class A {
public:
    static void *func(void *);
};

pthread_t t1;
pthread_create(&t1, NULL, &A::func, NULL);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM