+1  A: 

The member function MUST be static. Non-static have an implied "this" argument. Pass the pointer to your Whatever instance as the void* so that the static member can get at the instance.

Corey Trager
+6  A: 

Most C callbacks allow to specify an argument e.g.

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                   void *(*start_routine)(void*), void *arg);

So you could have

void myclass_doit(void* x)
{
  MyClass* c = reinterpret_cast<MyClass*>(x);
  c->doit();
}

pthread_create(..., &myclass_doit, (void*)(&obj));
Ian G
just a note that myclass_doit must have c linkage (ie. extern "C").
Greg Rogers
No, it doesn't. It's clearly being referenced from a C++ file.
keraba
This requires a separate wrapper for each callback. True it works, but it creates a huge mess of code management overhead.
Catskul
A: 

See this link

Basically, it's not directly possible, because: "Pointers to non-static members are different to ordinary C function pointers since they need the this-pointer of a class object to be passed. Thus ordinary function pointers and [pointers to] non-static member functions have different and incompatible signatures"

Seb Rose
+2  A: 

Use a C-function wrapper like this:

struct Whatever
{
    void Doit();
};

extern "C" static int DoItcallback (void * arg)
{
  Whatever * w = (Whatever *) arg;
  w->DoIt();
  return something;
}

Only works if you can pass the pointer to the class somehow. Most callback mechanisms allow this.

Afaik this is the only method to do this. You can't directly call a method from C without lots of hacking.

Nils Pipenbrinck
This requires a separate wrapper for each callback. True it works, but it creates a huge mess of code management overhead.
Catskul
A: 

While I haven't used it from C, for doing callbacks, I highly recommend looking at libsigc++. It's been exactly what I've needed a number of times when doing C++ callbacks.

bmdhacks
Doesn't libsigc++ define function objects (which are not callable from C) ? Just checking. Otherwise, yes, I agree that it is useful.
keraba
+3  A: 

Is the member function private? If not, use the standard idiom:

void* pthread_foo_caller(void* arg) {
    Foo* foo = static_cast<Foo*>(arg);
    foo->bar();
    return NULL;
}

If the member function is private, you can declare a static method in the class that takes a "this" pointer and calls the appropriate method. For example:

class Foo {
 public:
  static pthread_foo_caller(void* arg);
  ...
};

void* Foo::pthread_foo_caller(void* arg) {
    Foo* foo = static_cast<Foo*>(arg);
    foo->private_bar();
    return NULL;
}
hazzen
+1  A: 
Torbjörn Gyllebring
+4  A: 

The most concise solution is to define, in a header file shared by all your code:

template <typename T, void (T::*M)()>
void* thunk(
    void* p)
{
    T* pt = static_cast<T*>(p);

    (pt->*M)();

    return 0;
}

You probably want to define 4 versions: one each where the thunk returns void and void*, and one each where the member function returns void and void*. That way the compiler can match the best one, depending on the circumstances (and in fact it will complain if everything doesn't match.)

Then all you have to type every time you run into one of these situations is:

pthread_create(&pid, 0, &thunk<Whatever, &Whatever::doit>, &w);

This will even work when the method is private, as long as the method is referenced from within the class's code. (If not, I have to wonder why the code is referencing a private method.)

keraba
+1  A: 

One thing you should be aware of is that if you write code like this:

try {
    CallIntoCFunctionThatCallsMeBack((void *)this, fCallTheDoItFunction);
} catch (MyException &err)
{
   stderr << "badness.";
}

void fCallTheDoItFunction(void *cookie)
{
    MyClass* c = reinterpret_cast<MyClass*>(cookie);
    if (c->IsInvalid())
        throw MyException;
    c->DoIt();
}

You may run into some serious trouble depending on your compiler. It turns out that in some compilers while optimizing, they see a single C call in a try/catch block and exclaim with joy, "I am calling a C function that, because it is good old fashioned C, cannot throw! Calloo-cally! I shall remove all vestiges of the try/catch since it will never be reached.

Silly compiler.

Don't call into C that calls you back and expect to be able to catch.

plinth
Well, if your code is called by C (or other language) code, you need to make sure that no exceptions "escape" back into C/other anyway, so this advice is tautological. :-P
Chris Jester-Young