Using a C++ class member function as a C callback function

You can do that if the member function is static.

Non-static member functions of class A have an implicit first parameter of type class A* which corresponds to this pointer. That's why you could only register them if the signature of the callback also had the first parameter of class A* type.


You can also do this if the member function is not static, but it requires a bit more work (see also Convert C++ function pointer to c function pointer):

#include <stdio.h>
#include <functional>

template <typename T>
struct Callback;

template <typename Ret, typename... Params>
struct Callback<Ret(Params...)> {
   template <typename... Args> 
   static Ret callback(Args... args) {                    
      return func(args...);  
   }
   static std::function<Ret(Params...)> func; 
};

template <typename Ret, typename... Params>
std::function<Ret(Params...)> Callback<Ret(Params...)>::func;

void register_with_library(int (*func)(int *k, int *e)) {
   int x = 0, y = 1;
   int o = func(&x, &y);
   printf("Value: %i\n", o);
}

class A {
   public:
      A();
      ~A();
      int e(int *k, int *j);
};

typedef int (*callback_t)(int*,int*);

A::A() {
   Callback<int(int*,int*)>::func = std::bind(&A::e, this, std::placeholders::_1, std::placeholders::_2);
   callback_t func = static_cast<callback_t>(Callback<int(int*,int*)>::callback);      
   register_with_library(func);      
}

int A::e(int *k, int *j) {
   return *k - *j;
}

A::~A() { }

int main() {
   A a;
}

This example is complete in the sense that it compiles:

g++ test.cpp -std=c++11 -o test

You will need the c++11 flag. In the code you see that register_with_library(func) is called, where func is a static function dynamically bound to the member function e.


The problem is that method != function. The compiler will transform your method to something like that:

int e( A *this, int *k, int *j );

So, it's sure you can't pass it, because the class instance can't be passed as argument. One way to work around is to make the method as static, this way it would have the good type. But it won't any class instance, and access to non-static class members.

The other way is to declare a function with a static Pointer to a A initialised the first time. The function only redirect the call to the class :

int callback( int *j, int *k )
{
    static A  *obj = new A();
    a->(j, k);
}

Then you can register the callback function.


Well ...if you are on a win32 platform there is always the nasty Thunking way ...

Thunking in Win32: Simplifying callbacks to non-static member functions

It is a solution but I don't recommend using it.
It has a good explanation and it is nice to know it exists.