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.

4
  • 1
    The syntax for obtaining a pointer to member is &classname::membername. This however won't help you here, check stackoverflow.com/questions/1151582/… Commented Dec 5, 2012 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. Commented Dec 5, 2012 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. Commented Dec 5, 2012 at 15:02
  • OK, I changed the code as A::func but still same error. I will check the answers below. Commented Dec 5, 2012 at 15:04

4 Answers 4

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.

Sign up to request clarification or add additional context in comments.

Comments

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.

Comments

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

Comments

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.