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.
views:
850answers:
9Most 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));
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"
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.
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.
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;
}
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.)
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.