Orxonox  0.0.5 Codename: Arcturus
luatb_typed_stack.h
Go to the documentation of this file.
1 #ifndef LUATB_TYPED_STACK_H
2 #define LUATB_TYPED_STACK_H
3 
4 #include <type_traits>
5 #include <functional>
6 #include <lua.hpp>
7 #include "is_callable.h"
8 #include "core/CoreIncludes.h"
9 
10 
19 {
20 public:
21 
29  template<typename T>
30  static typename std::enable_if<!IsCallable<T>::value, T>::type getArgument(lua_State *lua)
31  {
32  T value = LuaTBTypedStack::getFromLuaStack<T>(lua);
33  lua_pop(lua, 1);
34  return value;
35  }
36 
47  template<typename T>
48  static typename std::enable_if<IsCallable<T>::value, T>::type getArgument(lua_State *lua)
49  {
50  // Here's the tricky part. Apparently, references in the registry can only
51  // be called once. This is why we always have to re-add it to the registry
52  // after every call. That means, we need a persistent variable for 'ref' and
53  // that's only possible with a pointer in this case.
54  int *ref = new int(luaL_ref(lua, LUA_REGISTRYINDEX));
55  LuaTBTypedStack::callbackRefs.push_back(std::unique_ptr<int>(ref));
56 
57  // 'decltype(&T::operator())' represents the function signature of the callable object.
59  }
60 
61 private:
62  template<typename T> struct GetLuaCallback;
63 
64  // Gets a value from the top of the lua stack and returns it with the proper type.
65  // Does not pop the value!
73  template<typename T> static T getFromLuaStack(lua_State *lua);
74 
75  // This class is only valid for std::function types. The type argument will not
76  // be a normal function signature because it is the signature of
77  // std::function<>::operator(), which is also the reason for the 'const'.
84  template<typename Ret, typename... Args>
85  struct GetLuaCallback<void (std::function<Ret(Args...)>::*)(Args...) const>
86  {
93  static std::function<void (Args...)> value(lua_State *lua, int *ref)
94  {
95  // We can't return 'callLuaFunction' directly, because we need the
96  // additional arguments 'lua' and 'ref' which we would like to hide
97  // from the user.
98  return [lua, ref](Args... args){callLuaFunction<Ret, Args...>(lua, ref, args...);};
99  }
100  };
101 
108  template<typename Ret, typename... Args>
109  static void callLuaFunction(lua_State *lua, int *ref, Args... args)
110  {
111  // Get the value of the callback from the registry and push it to the stack
112  lua_rawgeti(lua, LUA_REGISTRYINDEX, *ref);
113 
114  // Duplicate it on the stack so we can save it in the registry again after
115  // we called the callback.
116  lua_pushvalue(lua, 1);
117 
118  // We pass one extra argument in case the function has no arguments at all
119  pushArgumentsToLuaStack<Args...>(lua, args..., false);
120  lua_pcall(lua, sizeof...(args), 0, 0);
121 
122  // Release the old reference and save the function in the registry again
123  lua_unref(lua, *ref);
124  *ref = luaL_ref(lua, LUA_REGISTRYINDEX);
125  }
126 
135  template<typename T>
136  static void pushArgumentsToLuaStack(lua_State *, T)
137  { }
138 
145  template<typename First, typename... Args>
146  static void pushArgumentsToLuaStack(lua_State *lua, First first, Args... args)
147  {
148  pushToLuaStack(lua, first);
149  pushArgumentsToLuaStack<Args...>(lua, args...);
150  }
151 
159  template<typename T>
160  static void pushToLuaStack(lua_State *lua, T value);
161 
162  static std::list<std::unique_ptr<int> > callbackRefs;
163 };
164 
165 #endif // LUATB_TYPED_STACK_H
static T getFromLuaStack(lua_State *lua)
Get a value from the lua stack and convert it to type &#39;T&#39;.
static std::list< std::unique_ptr< int > > callbackRefs
Definition: luatb_typed_stack.h:163
STL namespace.
internal::ArgsMatcher< InnerMatcher > Args(const InnerMatcher &matcher)
Definition: gmock-generated-matchers.h:671
typedef void(ENET_CALLBACK *ENetPacketFreeCallback)(struct _ENetPacket *)
Represents a typed version of the lua stack.
Definition: luatb_typed_stack.h:18
static std::enable_if< IsCallable< T >::value, T >::type getArgument(lua_State *lua)
Get a function-type argument from the lua stack and convert it to type &#39;T&#39;.
Definition: luatb_typed_stack.h:48
Definition: luatb_typed_stack.h:62
static std::enable_if<!IsCallable< T >::value, T >::type getArgument(lua_State *lua)
Get a non-function argument from the lua stack and convert it to type &#39;T&#39;.
Definition: luatb_typed_stack.h:30
Definition: InputPrereqs.h:78
Defines several very important macros used to register objects, register classes, and to work with id...
static void pushArgumentsToLuaStack(lua_State *, T)
Pushes nothing onto the stack.
Definition: luatb_typed_stack.h:137
static void callLuaFunction(lua_State *lua, int *ref, Args...args)
Pushes all arguments to the lua stack and calls a lua function afterwards.
Definition: luatb_typed_stack.h:110
static void pushToLuaStack(lua_State *lua, T value)
Pushes a value to the lua stack.