1

I am using the variadic call pattern shown here. It works fine for ordinary C functions. But I want to use it with a member function and a tuple that explicitly has an instance pointer as the first argument.

I tried something like this:

template<typename Ret, typename C, typename...Args>
int methodWrapper(const string& name, Ret (C::*func)(Args...), lua_State* L)
{
    return wrap<Ret,C*,Args...>::wrapFunc(name, func, L);
}

But it fails to convert the pointer type:

cannot initialize a parameter of type 'void (*)(Object *, float, float)' with an lvalue of type 'void (Object::*)(float, float)'

In this case, the wrap function is templated, so the type of the pointer has to match exactly.

template<typename Ret, typename...Args>
struct wrap{
    static int wrapFunc(const string& name, Ret (*func)(Args...), lua_State* L)
    {
        ...
    }
};

How to I explicitly convert a member function pointer into an ordinary function pointer that takes the this pointer as its first argument?

EDIT: for those that have linked me to this question, it is not the same. I do not have to pass a plain C function pointer to an existing API with a specific interface. And I am not trying to bind a member function to a specific object. This question also does not deal with variadic call or tuples.

Community
  • 1
  • 1
stands2reason
  • 616
  • 1
  • 7
  • 18
  • Possible duplicate of [Convert C++ function pointer to c function pointer](http://stackoverflow.com/questions/19808054/convert-c-function-pointer-to-c-function-pointer) – Paolo M Dec 02 '15 at 16:27
  • Or http://stackoverflow.com/questions/19808054/convert-c-function-pointer-to-c-function-pointer, if you prefer – Paolo M Dec 02 '15 at 16:28
  • And maybe http://stackoverflow.com/questions/4210710/cast-pointer-to-member-function-to-normal-pointer – Paolo M Dec 02 '15 at 16:28
  • You should know that `lua_CFunction` has type `extern "C" int (*) (lua_State *L)`. That you can pass `int (*)(lua_State *L)` instead is a bug in nearly every compiler and isn't standard conformant. – Simple Dec 02 '15 at 16:31
  • What about creating a lambda and passing that in? What does `wrapFunc` do with the function it receives? – Claudiu Dec 02 '15 at 16:40
  • It uses a variadic template to convert Lua parameters to the appropriate C type, and then does a variadic call. This is why I can't use a lambda or bind: I don't have the this pointer, it is unpacked from the Lua arguments. I would have a convert partial specialization that expects a table and extracts the userdata this pointer. – stands2reason Dec 02 '15 at 17:03
  • I explained why the linked question is in fact not a dupe. That question was like the opposite of my question: the asker wanted to convert a C++ member function a C function pointer, but didn't seem to understand that this would involve explicitly passing as instance pointer as an argument, which is exactly what I did. – stands2reason Dec 03 '15 at 15:45

1 Answers1

0

std::mem_fn does this.

In order to make the template match: I had to explicitly declare the args tuple as a Class pointer followed by the parameter pack:

template<typename C, typename...Args>
struct wrapMethod<void,C,Args...>{
    static int wrap(const string& name, void (C::*func)(Args...), lua_State* L)
    {
        tuple<C*, Args...> args = cargs<C*,Args...>::getCArgs(L, name);

        //Return type (first template parameter) cannot be inferred.
        variadic_call<void>(mem_fn(func), args);

        return 0;
    }
};
stands2reason
  • 616
  • 1
  • 7
  • 18