Last active
November 5, 2018 07:43
-
-
Save Jayatubi/7d2388b9d762b52a8ec2806d94031de4 to your computer and use it in GitHub Desktop.
TFunctionProxy
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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