Skip to content

Instantly share code, notes, and snippets.

@Jayatubi
Last active November 5, 2018 07:43
Show Gist options
  • Save Jayatubi/7d2388b9d762b52a8ec2806d94031de4 to your computer and use it in GitHub Desktop.
Save Jayatubi/7d2388b9d762b52a8ec2806d94031de4 to your computer and use it in GitHub Desktop.
TFunctionProxy
template<typename LambdaType, typename ReturnType, typename ... ArgTypes>
struct LambdaPrototype
{
typedef LambdaType* FuncType;
static ReturnType invoke(lua_State* L, void* ptr, ArgTypes&& ... args)
{
return Func != nullptr ? (*Func)(std::forward<ArgTypes>(args)...) : ReturnType();
}
class TFunctionProxy : public TFunction<ReturnType(ArgTypes...)>
{
public:
TFunctionProxy(lua_State* l, int p)
: L(l)
, RefCount(nullptr)
{
lua_pushvalue(L, p);
FuncRef = luaL_ref(L, LUA_REGISTRYINDEX);
RefCount = new int;
(*RefCount) = 1;
}
TFunctionProxy(const TFunctionProxy& right)
: L(right.L)
, FuncRef(right.FuncRef)
, RefCount(right.RefCount)
{
if (RefCount != nullptr)
{
(*RefCount)++;
}
}
TFunctionProxy(TFunctionProxy&& right)
: L(right.L)
, FuncRef(right.FuncRef)
, RefCount(right.RefCount)
{
right.L = nullptr;
right.FuncRef = 0;
right.RefCount = nullptr;
}
~TFunctionProxy()
{
if (RefCount != nullptr)
{
(*RefCount)--;
if (*RefCount == 0)
{
luaL_unref(L, LUA_REGISTRYINDEX, FuncRef);
FuncRef = 0;
delete RefCount;
}
}
}
template<typename T>
static ReturnType WrapReturn(lua_State* L, typename std::enable_if<std::is_void<T>::value, int>::type = 0)
{
}
template<typename T>
static ReturnType WrapReturn(lua_State* L, typename std::enable_if<!std::is_void<T>::value, int>::type = 0)
{
static ReturnType Impl(lua_State* L)
{
ReturnType result = ArgOperator::readArg<ReturnType>(L, -1);
lua_pop(L, 1);
return result;
}
};
ReturnType operator()(ArgTypes ... args) const
{
if (FuncRef != 0)
{
int top = lua_gettop(L);
lua_geti(L, LUA_REGISTRYINDEX, FuncRef);
PushArgs(L, args ...);
lua_pcall(L, sizeof...(args), LUA_MULTRET, 0);
int n = lua_gettop(L) - top;
if (n == 1)
{
return WrapReturn<ReturnType>(L);
}
}
return ReturnType();
}
static void PushArgs(lua_State* L)
{
}
template<typename F, typename ... R>
static void PushArgs(lua_State* L, F f, R ... r)
{
LuaObject::push(L, f);
PushArgs(L, r ... );
}
private:
lua_State* L;
int FuncRef;
int* RefCount;
};
static TFunction<ReturnType(ArgTypes...)> makeTfunctionProxy(lua_State* L, int p)
{
return TFunctionProxy(L, p);
}
static int LuaCFunction(lua_State* L)
{
return FunctionBind<decltype(&invoke), invoke, 1>::invoke(L, nullptr);
}
static FuncType Func;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment