Casting Between void* and a Pointer to Member Function
In the world of C programming, casting between void* and a pointer to a member function can be a real headache. Let's dive into a specific problem that illustrates this challenge.
Consider the following code snippet:
<code class="cpp">template <class T> int call_int_function(lua_State *L) { void (T::*method)(int, int) = reinterpret_cast<void (T::*)(int, int)>(lua_touserdata(L, lua_upvalueindex(1))); // <-- problematic line T *obj = reinterpret_cast<T *>(lua_touserdata(L, 1)); (obj->*method)(lua_tointeger(L, 2), lua_tointeger(L, 3)); return 0; }</code>
Here, GCC complains that the cast from void* to void (T::*)(int, int) is invalid. So, what's the solution?
Understanding the Problem
Understanding the problem requires delving deeper into the nature of pointers to member functions. Unlike regular pointers that point to addresses, pointers to member functions are much more complex. They contain information specific to the compiler implementation and the layout of class members.
Alternative Approaches
The truth is, you can't directly cast void* to a pointer to a member function. The suggested solution involves wrapping the member function in a regular function and returning that instead. Here's how:
<code class="cpp">template <class T> int call_int_function(lua_State *L) { void (*method)(T*, int, int) = reinterpret_cast<void (*)(T*, int, int)>(lua_touserdata(L, lua_upvalueindex(1))); T *obj = reinterpret_cast<T *>(lua_touserdata(L, 1)); method(obj, lua_tointeger(L, 2), lua_tointeger(L, 3)); return 0; }</code>
This approach works because we are now casting to a regular function pointer, which can be stored in void* and retrieved without issue.
The above is the detailed content of How to Safely Cast Between `void*` and a Pointer to a Member Function in C ?. For more information, please follow other related articles on the PHP Chinese website!