Casting between void * and a pointer to member function

Solution 1:

You cannot cast a pointer-to-member to void * or to any other "regular" pointer type. Pointers-to-members are not addresses the way regular pointers are. What you most likely will need to do is wrap your member function in a regular function. The C++ FAQ Lite explains this in some detail. The main issue is that the data needed to implement a pointer-to-member is not just an address, and in fact varies tremendously based on the compiler implementation.

I presume you have control over what the user data lua_touserdata is returning. It can't be a pointer-to-member since there isn't a legal way to get this information back out. But you do have some other choices:

  • The simplest choice is probably to wrap your member function in a free function and return that. That free function should take the object as its first argument. See the code sample below.

  • Use a technique similar to that of Boost.Bind's mem_fun to return a function object, which you can template on appropriately. I don't see that this is easier, but it would let you associate the more state with the function return if you needed to.

Here's a rewrite of your function using the first way:

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;
}

Solution 2:

It is possible to convert pointer to member functions and attributes using unions:

// helper union to cast pointer to member
template<typename classT, typename memberT>
union u_ptm_cast {
    memberT classT::*pmember;
    void *pvoid;
};

To convert, put the source value into one member, and pull the target value out of the other.

While this method is practical, I have no idea if it's going to work in every case.