/* Luwra * Minimal-overhead Lua wrapper for C++ * * Copyright (C) 2015, Ole Krüger */ #ifndef LUWRA_WRAPPERS_H_ #define LUWRA_WRAPPERS_H_ #include "common.h" #include "types.h" #include "stack.h" LUWRA_NS_BEGIN namespace internal { // Function helpers template struct FunctionWrapper { static_assert( sizeof(T) == -1, "The FunctionWrapper template expects a function signature as parameter" ); }; template <> struct FunctionWrapper { template static int invoke(State*) { funptr(); return 0; } }; template struct FunctionWrapper { template static int invoke(State* state) { return Value::push(state, funptr()); } }; template struct FunctionWrapper { template static int invoke(State* state) { apply(state, funptr); return 0; } }; template struct FunctionWrapper { template static int invoke(State* state) { return Value::push( state, apply(state, funptr) ); } }; // Method helpers template struct MethodWrapper { static_assert( sizeof(T) == -1, "The MethodWrapper template expects a type name and a function signature as parameter" ); }; template struct MethodWrapper { using MethodPointerType = R (T::*)(A...); using FunctionSignature = R (T*, A...); template static R delegate(T* parent, A... args) { return (parent->*MethodPointer)(std::forward(args)...); } }; } /** * Assuming its parameters can be retrieved from the Lua stack, ordinary functions can be wrapped * using the `WrapFunction` instance in order to produce a C function which can be used by the * Lua VM. * * Assuming your function has the following signature: * * R my_fun(A0, A1 ... An); * * Generate a Lua-compatible like so: * * CFunction wrapped_fun = WrapFunction; */ template < typename S, S* FunctionPointer > constexpr CFunction WrapFunction = &internal::FunctionWrapper::template invoke; /** * Works similiar to `WrapFunction`. Given a class or struct declaration as follows: * * struct T { * R my_method(A0, A1 ... An); * }; * * You might wrap this method easily: * * CFunction wrapped_meth = WrapMethod; * * In Lua, assuming `instance` is a userdata instance of type `T`, x0, x1 ... xn are instances * of A0, A1 ... An, and the method has been bound as `my_method`; it is possible to invoke the * method like so: * * instance:my_method(x0, x1 ... xn) */ template < typename T, typename S, typename internal::MethodWrapper::MethodPointerType MethodPointer > constexpr CFunction WrapMethod = WrapFunction< internal::MethodWrapper::FunctionSignature, internal::MethodWrapper::template delegate >; LUWRA_NS_END #endif