0

I have a question related with C++ and threads. I am more familiar with Java than C++ and this error is confusing me.

Imagine that in x.h file I have a class such as:

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:

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."

What should I do to fix this?

Thanks.

Luke Clifford
  • 112
  • 12
sjor
  • 1,438
  • 5
  • 17
  • 22
  • 1
    The syntax for obtaining a pointer to member is `&classname::membername`. This however won't help you here, check http://stackoverflow.com/questions/1151582/pthread-function-from-a-class – chill Dec 05 '12 at 14:44
  • I got it and I will change the code but the answer in the question is a bit different than my case. He creates an instance of class and then creates the thread but I create the thread in a method of the class. – sjor Dec 05 '12 at 14:58
  • it doesn't matter where you create the thread, as far as `pthread_create` is concerned - the syntax for getting a pointer to member is the same and `pthread_create` will not accept an argument of a pointer to member type anyway. – chill Dec 05 '12 at 15:02
  • OK, I changed the code as A::func but still same error. I will check the answers below. – sjor Dec 05 '12 at 15:04

4 Answers4

3

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

What you need here is a static wrapper method which matches pthread_create's expectations of the thread start routine. 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 type of wrapper is commonly known as a "thunk", since it adapts one calling convention to another.

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.

Community
  • 1
  • 1
zwol
  • 135,547
  • 38
  • 252
  • 361
2

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.

Wutz
  • 2,246
  • 13
  • 15
1

use one of:

  • boost::thread
  • C++11
  • some other C++ library threads (a plenty of them)
  • 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. then in static function just call desired method using instance and method address obtained from parameter
zaufi
  • 6,811
  • 26
  • 34
0

In 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. 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.

Example:

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

pthread_t t1;
pthread_create(&t1, NULL, &A::func, NULL);
Olaf Dietsche
  • 72,253
  • 8
  • 102
  • 198