If you use MSVC, and target x86-32 (not x86-64), you may use __stdcall convention for member function. (__cdecl works too)
With __stdcall this will be passed as first parameter, so you can write
typedef void(__stdcall *callback_t)(void* arg);
void set_callback(callback_t callback, void* callbackParameter);
struct Foo
{
int x;
void __stdcall someCallback() { this->x = 1; }
};
but
Foo foo;
set_callback((callback_t)&Foo::someCallback, this);
Will not work: you can't directly cast member function pointer to pointer by standard. You should use a workaround to make this working:
First, assert that &Foo::someCallback has the same size as void*
static_assert(sizeof(&Foo::someCallback) == sizeof(void*), "");
// or assert()
This assert may fail, if there may be multiple inheritance, and someCallback is virtual.
To disallow multiple inheritance, use __single_inheritance keyword:
struct __single_inheritance Foo { /* ....*/ };
Second, you should cast &Foo::someCallback to callback_t by using
union
{
void(__stdcall Foo::*src)();
callback_t dst;
} u = {&Foo::someCallback};
set_callback(u.dst, this);
or
void(__stdcall Foo::*temp)() = &Foo::someCallback;
set_callback(*(callback_t*)&temp, this);
It works only if you can pass this to callback as first parameter.
If you can't, you can try to dynamically generate callback stubs in assembly :) Allocate an executable memory and write there
B9 XX XX XX XX mov ecx, <this>
68 XX XX XX XX push <function member address>
C3 ret
It will be callback stub, which will convert __stdcall to __thiscall.