Pioneer
LuaMetaType.h
Go to the documentation of this file.
1 // Copyright © 2008-2023 Pioneer Developers. See AUTHORS.txt for details
2 // Licensed under the terms of the GPL v3. See licenses/GPL-3.txt
3 
4 #pragma once
5 
6 #include "Lua.h"
7 #include "LuaCall.h"
8 #include "LuaManager.h"
9 #include "LuaPushPull.h"
10 #include "LuaTable.h"
11 
12 /*
13  * LuaMetaType is a C++ -> Lua binding system intended to drastically
14  * simplify the amount of time and code needed to write often-repetitive
15  * glue code to pull arguments from Lua and pass them to a C++ function,
16  * then push the result back on the Lua stack.
17  *
18  * Usage comes in two flavors based on what you're intending to bind:
19  *
20  * LuaObjects (e.g. classes and structs):
21  *
22  * In the regular LuaObject<T>::RegisterClass method, create a static
23  * LuaMetaType<T> object and call CreateMetaType(lua_State *) on it.
24  * Once done, between any StartRecording() and StopRecording() pair,
25  * chain AddFunction and AddMember calls to build the Lua binding like so:
26  *
27  * > .AddFunction("name", &T::SomeFunc)
28  * > .AddMember("name", &T::someMember)
29  *
30  * Call LuaObjectBase::CreateClass(&metaType) afterwards and you're done.
31  *
32  * Generic "Namespace" bindings (e.g. LuaEngine):
33  *
34  * These are similar to the above, simply create a LuaMetaTypeGeneric
35  * object. Instead of binding c++ member functions however, you can
36  * bind any C++ free function - LuaMetaTypeGeneric doesn't have a concept
37  * of a 'this object' and is intended to simplify binding libraries of
38  * stateless functions to Lua (e.g. ImGui).
39  *
40  * > .AddFunction("NewLine", &ImGui::NewLine)
41  */
42 
43 // Base class for the LuaMetaType binding system
45 public:
46  LuaMetaTypeBase(const char *name) :
47  m_typeName(name)
48  {}
49 
50  // Creates and registers the lua-side object for this type.
51  void CreateMetaType(lua_State *l);
52 
53  const char *GetTypeName() const { return m_typeName.c_str(); }
54 
55  const char *GetParent() const { return m_parent.c_str(); }
56 
57  void SetParent(const char *parent) { m_parent = parent; }
58 
59  // Push the metatable to the lua stack.
60  void GetMetatable() const;
61 
62  // Returns true if the metatype has been correctly set up.
63  bool IsValid() const { return m_lua && m_ref != LUA_NOREF; }
64 
65  // Call this function to set the lua stack up to begin recording members
66  // and methods into the metatype.
67  // It is invalid to call other functions outside a StartRecording / StopRecording pair.
69  {
70  assert(IsValid());
71  assert(m_index == 0);
72 
73  GetMetatable();
74  m_index = lua_gettop(m_lua);
75  }
76 
77  // Stop recording and remove the metatype from the stack
79  {
80  assert(IsValid());
81  assert(m_index != 0);
82  lua_remove(m_lua, m_index);
83  m_index = 0;
84  }
85 
86  // Get all valid method/attribute names for the object on the top of the stack.
87  // Mainly intended to be used by the console, though it can also be used for
88  // debug dumping of properties, attributes, and methods
89  static void GetNames(std::vector<std::string> &names, const std::string &prefix = "", bool methodsOnly = false);
90 
91  // Get the lua-side metatable from a type name instead of a LuaRef.
92  static bool GetMetatableFromName(lua_State *l, const char *name);
93 
94  // A replacement for luaL_testudata that is metatype-aware
95  static void *TestUserdata(lua_State *l, int index, const char *name);
96 
97  // A replacement for luaL_checkudata that is metatype-aware
98  static void *CheckUserdata(lua_State *l, int index, const char *name);
99 
100 protected:
101  //=========================================================================
102  // LuaMetaTypeGeneric support:
103  //=========================================================================
104 
105  // C++ free functions taking any set of arguments and returning a value or void
106  template <typename Rt, typename... Args>
107  using free_function = Rt (*)(Args...);
108 
109  // Overload for free functions returning a value
110  template <typename Rt, typename... Args>
111  typename std::enable_if<!std::is_same<Rt, void>::value, int>::type static free_fn_wrapper_(lua_State *L)
112  {
113  if (size_t(lua_gettop(L)) < sizeof...(Args))
114  return luaL_error(L, "Invalid number of arguments for function %s (have %d, need %lu)",
115  lua_tostring(L, lua_upvalueindex(1)), lua_gettop(L), sizeof...(Args));
116 
117  auto fn = PullFreeFunction<free_function<Rt, Args...>>(L, lua_upvalueindex(2));
118  Rt ret = pi_lua_multiple_call(L, 1, fn);
119  LuaPush<Rt>(L, ret);
120 
121  return 1;
122  }
123 
124  // Overload for functions returning void
125  template <typename Rt, typename... Args>
126  typename std::enable_if<std::is_same<Rt, void>::value, int>::type static free_fn_wrapper_(lua_State *L)
127  {
128  if (size_t(lua_gettop(L)) < sizeof...(Args))
129  return luaL_error(L, "Invalid number of arguments for function %s (have %d, need %lu)",
130  lua_tostring(L, lua_upvalueindex(1)), lua_gettop(L), sizeof...(Args));
131 
132  auto fn = PullFreeFunction<free_function<Rt, Args...>>(L, lua_upvalueindex(2));
133  pi_lua_multiple_call(L, 1, fn);
134 
135  return 0;
136  }
137 
138  //=========================================================================
139  // LuaMetaType<T> support:
140  //=========================================================================
141 
142  // Direct member pointer access (for structs, etc.)
143  template <typename T, typename Dt>
144  using member_pointer = Dt T::*;
145 
146  template <typename T, typename Dt>
147  static int member_wrapper_(lua_State *L)
148  {
149  T *ptr = LuaPull<T *>(L, 1);
150  const char *name = lua_tostring(L, lua_upvalueindex(1));
151 
152  if (!ptr)
153  return luaL_error(L, "Null or invalid userdata accessed for property %s", name);
154 
155  if (lua_gettop(L) > 2)
156  return luaL_error(L, "Invalid number of arguments for property getter/setter %s", name);
157 
158  auto &t = PullPointerToMember<member_pointer<T, Dt>>(L, lua_upvalueindex(2));
159  if (lua_gettop(L) == 1) {
160  LuaPush<Dt>(L, ptr->*(t));
161  return 1;
162  } else {
163  (ptr->*(t)) = LuaPull<Dt>(L, 2);
164  return 0;
165  }
166  }
167 
168  //=========================================================================
169 
170  // "Member Free Function" access: like lua_CFunction but with an automatic
171  // this-object pointer passed to the function for simplicity
172  template <typename T>
173  using member_cfunction = int (*)(lua_State *, T *);
174 
175  template <typename T>
176  static int member_cfn_wrapper_(lua_State *L)
177  {
178  T *ptr = LuaPull<T *>(L, 1);
179  const char *name = lua_tostring(L, lua_upvalueindex(1));
180  luaL_checktype(L, lua_upvalueindex(2), LUA_TLIGHTUSERDATA);
181 
182  if (!ptr)
183  return luaL_error(L, "Invalid userdata accessed for function %s", name);
184 
185  auto fn = PullFreeFunction<member_cfunction<T>>(L, lua_upvalueindex(2));
186  return fn(L, ptr);
187  }
188 
189  // Bind two member free functions into a getter-setter pair for an attr
190  template <typename T>
191  static int getter_member_cfn_wrapper_(lua_State *L)
192  {
193  T *ptr = LuaPull<T *>(L, 1);
194  const char *name = lua_tostring(L, lua_upvalueindex(1));
195  auto getter = PullFreeFunction<member_cfunction<T>>(L, lua_upvalueindex(2));
196 
197  if (!ptr)
198  return luaL_error(L, "Null or invalid userdata accessed for property %s", name);
199 
200  if (lua_gettop(L) > 2)
201  return luaL_error(L, "Invalid number of arguments for property getter/setter %s", name);
202 
203  if (lua_gettop(L) > 1) {
204  auto setter = PullFreeFunction<member_cfunction<T>>(L, lua_upvalueindex(3));
205  if (setter != nullptr)
206  return setter(L, ptr);
207  else
208  return luaL_error(L, "Attempt to call undefined setter for property %s", name);
209  }
210 
211  return getter(L, ptr);
212  }
213 
214  //=========================================================================
215 
216  // C++ member function pointer access: using template magic, this assembles
217  // all of the bridge code needed to pull values from Lua and pass the return value back
218  template <typename T, typename Rt, typename... Args>
219  using member_function = Rt (T::*)(Args...);
220 
221  template <typename T, typename Rt, typename... Args>
222  using const_member_function = Rt (T::*)(Args...) const;
223 
224  // Overload for function returning a value
225  template <typename T, typename Rt, typename... Args>
226  typename std::enable_if<!std::is_same<Rt, void>::value, int>::type static member_fn_wrapper_(lua_State *L)
227  {
228  T *ptr = LuaPull<T *>(L, 1);
229  const char *name = lua_tostring(L, lua_upvalueindex(1));
230 
231  if (!ptr)
232  return luaL_error(L, "Invalid userdata accessed for function %s", name);
233 
234  if (size_t(lua_gettop(L) - 1) < sizeof...(Args))
235  return luaL_error(L, "Invalid number of arguments for function %s", name);
236 
237  auto &fn = PullPointerToMember<member_function<T, Rt, Args...>>(L, lua_upvalueindex(2));
238  Rt ret = pi_lua_multiple_call(L, 1, ptr, fn);
239  LuaPush<Rt>(L, ret);
240 
241  return 1;
242  }
243 
244  // Overload for function returning void
245  template <typename T, typename Rt, typename... Args>
246  typename std::enable_if<std::is_same<Rt, void>::value, int>::type static member_fn_wrapper_(lua_State *L)
247  {
248  T *ptr = LuaPull<T *>(L, 1);
249  const char *name = lua_tostring(L, lua_upvalueindex(1));
250 
251  if (!ptr)
252  return luaL_error(L, "Invalid userdata accessed for function %s", name);
253 
254  if (size_t(lua_gettop(L) - 1) < sizeof...(Args))
255  return luaL_error(L, "Invalid number of arguments for function %s", name);
256 
257  auto &fn = PullPointerToMember<member_function<T, Rt, Args...>>(L, lua_upvalueindex(2));
258  pi_lua_multiple_call(L, 1, ptr, fn);
259 
260  return 0;
261  }
262 
263  // T::GetName / T::SetName glue code to wrap into a single attr function
264  template <typename T, typename Dt, typename Dt2>
265  static int getter_member_fn_wrapper_(lua_State *L)
266  {
267  T *ptr = LuaPull<T *>(L, 1);
268  const char *name = lua_tostring(L, lua_upvalueindex(1));
269  auto &getter = PullPointerToMember<member_function<T, Dt>>(L, lua_upvalueindex(2));
270 
271  if (!ptr)
272  return luaL_error(L, "Null or invalid userdata accessed for property %s", name);
273 
274  if (lua_gettop(L) > 2)
275  return luaL_error(L, "Invalid number of arguments for property getter/setter %s", name);
276 
277  if (lua_gettop(L) > 1) {
278  auto &setter = PullPointerToMember<member_function<T, void, Dt2>>(L, lua_upvalueindex(3));
279  if (setter != nullptr) {
280  pi_lua_multiple_call(L, 1, ptr, setter);
281  return 0;
282  } else
283  return luaL_error(L, "Attempt to call undefined setter for property %s", name);
284  } else {
285  Dt value = pi_lua_multiple_call(L, 1, ptr, getter);
286  LuaPush<Dt>(L, value);
287  return 1;
288  }
289  }
290 
291  //=========================================================================
292  // Generic support for getting function pointers in and out of lua:
293  //=========================================================================
294 
295  template <typename MemT>
296  static void PushPointerToMember(lua_State *L, MemT obj)
297  {
298  *reinterpret_cast<MemT *>(lua_newuserdata(L, sizeof(MemT))) = obj;
299  }
300 
301  template <typename MemT>
302  static MemT &PullPointerToMember(lua_State *L, int idx)
303  {
304  return *reinterpret_cast<MemT *>(lua_touserdata(L, idx));
305  }
306 
307  template <typename T>
308  static void PushFreeFunction(lua_State *L, T obj)
309  {
310  static_assert(sizeof(T) == sizeof(void *), "Free functions cannot be 'fat' lambdas!");
311  lua_pushlightuserdata(L, reinterpret_cast<void *>(obj));
312  }
313 
314  template <typename T>
315  static T PullFreeFunction(lua_State *L, int index)
316  {
317  return reinterpret_cast<T>(lua_touserdata(L, index));
318  }
319 
320  // Pushes a copy of the metatable's attribute table to the stack
321  void GetAttrTable(lua_State *L, int index)
322  {
323  luaL_getsubtable(L, index, "attrs");
324  }
325 
326  // Pushes a copy of the metatable's attribute table to the stack
327  void GetMethodTable(lua_State *L, int index)
328  {
329  luaL_getsubtable(L, index, "methods");
330  }
331 
332  std::string m_typeName;
333  std::string m_parent;
334 
335  lua_State *m_lua;
336  // the reference id of the metatable
337  int m_ref = LUA_NOREF;
338  // the position of the metatable on the stack while recording
339  int m_index = 0;
340 };
341 
343 public:
345 
346  LuaMetaTypeGeneric(const char *name) :
347  LuaMetaTypeBase(name)
348  {}
349 
351  {
353  return *this;
354  }
355 
357  {
359  return *this;
360  }
361 
362  Self &SetProtected(bool enabled)
363  {
364  m_protected = enabled;
365  return *this;
366  }
367 
368  Self &AddMember(const char *name, lua_CFunction getter)
369  {
371 
372  lua_pushcfunction(m_lua, getter);
373  if (m_protected)
374  lua_pushcclosure(m_lua, secure_trampoline, 1);
375 
376  lua_setfield(m_lua, -2, name);
377  lua_pop(m_lua, 1);
378  return *this;
379  }
380 
381  Self &AddFunction(const char *name, lua_CFunction func)
382  {
384 
385  lua_pushcfunction(m_lua, func);
386  if (m_protected)
387  lua_pushcclosure(m_lua, secure_trampoline, 1);
388 
389  lua_setfield(m_lua, -2, name);
390  lua_pop(m_lua, 1);
391  return *this;
392  }
393 
394  template <typename Rt, typename... Args>
395  Self &AddFunction(const char *name, free_function<Rt, Args...> func)
396  {
398 
399  lua_pushstring(m_lua, (m_typeName + "." + name).c_str());
400  PushFreeFunction(m_lua, func);
401  lua_pushcclosure(m_lua, &free_fn_wrapper_<Rt, Args...>, 2);
402  if (m_protected)
403  lua_pushcclosure(m_lua, &secure_trampoline, 1);
404 
405  lua_setfield(m_lua, -2, name);
406  lua_pop(m_lua, 1);
407  return *this;
408  }
409 
410  Self &AddMeta(const char *name, lua_CFunction func)
411  {
412  lua_pushcfunction(m_lua, func);
413  if (m_protected)
414  lua_pushcclosure(m_lua, secure_trampoline, 1);
415 
416  lua_setfield(m_lua, m_index, name);
417 
418  return *this;
419  }
420 
421  template <typename Rt, typename... Args>
422  Self &AddMeta(const char *name, free_function<Rt, Args...> func)
423  {
424  lua_pushstring(m_lua, (m_typeName + "." + name).c_str());
425  PushFreeFunction(m_lua, func);
426  lua_pushcclosure(m_lua, &free_fn_wrapper_<Rt, Args...>, 2);
427  if (m_protected)
428  lua_pushcclosure(m_lua, &secure_trampoline, 1);
429 
430  lua_setfield(m_lua, m_index, name);
431 
432  return *this;
433  }
434 
435  Self &AddCallCtor(lua_CFunction func)
436  {
438  lua_getmetatable(m_lua, -1);
439 
440  lua_pushcfunction(m_lua, func);
441  if (m_protected)
442  lua_pushcclosure(m_lua, secure_trampoline, 1);
443 
444  lua_setfield(m_lua, -2, "__call");
445  lua_pop(m_lua, 2);
446 
447  return *this;
448  }
449 
450  Self &AddNewCtor(lua_CFunction func)
451  {
453 
454  lua_pushcfunction(m_lua, func);
455  if (m_protected)
456  lua_pushcclosure(m_lua, secure_trampoline, 1);
457 
458  lua_setfield(m_lua, -2, "New");
459  lua_pop(m_lua, 1);
460  return *this;
461  }
462 
463 private:
464  bool m_protected = false;
465 };
466 
467 template <typename T>
468 class LuaMetaType : public LuaMetaTypeBase {
469 public:
470  using Self = LuaMetaType;
471 
472  LuaMetaType(const char *name) :
473  LuaMetaTypeBase(name)
474  {}
475 
477  {
479  return *this;
480  }
481 
483  {
485  return *this;
486  }
487 
488  // All functions and members pushed while protection is enabled will error
489  // when accessed by a non-trusted lua script.
490  void SetProtected(bool enabled) { m_protected = enabled; }
491 
492  // Bind a raw C++ data member to Lua.
493  // Obviously, the member in question must be publically accessible, or
494  // LuaMetaTypeBase must be marked as a friend class.
495  template <typename Dt>
496  Self &AddMember(const char *name, member_pointer<T, Dt> t)
497  {
498  lua_State *L = m_lua;
499  GetAttrTable(L, m_index);
500 
501  lua_pushstring(L, (m_typeName + "." + name).c_str());
502  PushPointerToMember(L, t);
503  lua_pushcclosure(L, &member_wrapper_<T, Dt>, 2);
504  if (m_protected)
505  lua_pushcclosure(L, &secure_trampoline, 1);
506 
507  lua_setfield(L, -2, name);
508  lua_pop(L, 1);
509 
510  return *this;
511  }
512 
513  // Bind a pseudo-member to Lua via a free-function getter and setter.
514  // The getter and setter are responsible for pulling parameters from Lua.
515  Self &AddMember(const char *name, member_cfunction<T> getter, member_cfunction<T> setter = nullptr)
516  {
517  lua_State *L = m_lua;
518  GetAttrTable(L, m_index);
519 
520  lua_pushstring(L, (m_typeName + "." + name).c_str());
521  PushFreeFunction(L, getter);
522  PushFreeFunction(L, setter);
523  lua_pushcclosure(L, &getter_member_cfn_wrapper_<T>, 3);
524  if (m_protected)
525  lua_pushcclosure(L, &secure_trampoline, 1);
526 
527  lua_setfield(L, -2, name);
528  lua_pop(L, 1);
529 
530  return *this;
531  }
532 
533  // Magic to allow binding a const function to Lua. Take care to ensure that you do not
534  // push a const object to lua, or this code will become undefined behavior.
535  template <typename Dt, typename Dt2 = Dt>
536  Self &AddMember(const char *name, const_member_function<T, Dt> getter, member_function<T, void, Dt2> setter = nullptr)
537  {
538  return AddMember(name, reinterpret_cast<member_function<T, Dt>>(getter), setter);
539  }
540 
541  // Bind a pseudo-member to Lua via a member-function getter and setter.
542  // The parameter will automatically be pulled from Lua and passed to the setter.
543  template <typename Dt, typename Dt2 = Dt>
544  Self &AddMember(const char *name, member_function<T, Dt> getter, member_function<T, void, Dt2> setter = nullptr)
545  {
546  lua_State *L = m_lua;
547  GetAttrTable(L, m_index);
548 
549  lua_pushstring(L, (m_typeName + "." + name).c_str());
550  PushPointerToMember(L, getter);
551  PushPointerToMember(L, setter);
552  lua_pushcclosure(L, &getter_member_fn_wrapper_<T, Dt, Dt2>, 3);
553  if (m_protected)
554  lua_pushcclosure(L, &secure_trampoline, 1);
555 
556  lua_setfield(L, -2, name);
557  lua_pop(L, 1);
558 
559  return *this;
560  }
561 
562  // Magic to allow binding a const function to Lua. Take care to ensure that you do not
563  // push a const object to lua, or this code will become undefined behavior.
564  template <typename Rt, typename... Args>
566  {
567  return AddFunction(name, reinterpret_cast<member_function<T, Rt, Args...>>(fn));
568  }
569 
570  // Bind a member function to Lua.
571  // Parameters will automatically be pulled from Lua and be passed to the function.
572  // It is the responsiblity of the programmer to ensure a valid LuaPull implementation
573  // is available for each parameter's time.
574  // If the function has a non-void return type, its return value will automatically be
575  // pushed to Lua.
576  template <typename Rt, typename... Args>
578  {
579  lua_State *L = m_lua;
581 
582  lua_pushstring(L, (m_typeName + "." + name).c_str());
583  PushPointerToMember(L, fn);
584  lua_pushcclosure(L, &member_fn_wrapper_<T, Rt, Args...>, 2);
585  if (m_protected)
586  lua_pushcclosure(L, &secure_trampoline, 1);
587 
588  lua_setfield(L, -2, name);
589  lua_pop(L, 1);
590 
591  return *this;
592  }
593 
594  // Bind a free function to Lua.
595  // The self parameter will be automatically provided, but the function
596  // is responsible for pulling the rest of its parameters and pushing the
597  // appropriate number of return values.
598  Self &AddFunction(const char *name, member_cfunction<T> fn)
599  {
600  lua_State *L = m_lua;
602 
603  lua_pushstring(L, (m_typeName + "." + name).c_str());
604  PushFreeFunction(L, fn);
605  lua_pushcclosure(L, &member_cfn_wrapper_<T>, 2);
606  if (m_protected)
607  lua_pushcclosure(L, &secure_trampoline, 1);
608 
609  lua_setfield(L, -2, name);
610  lua_pop(L, 1);
611 
612  return *this;
613  }
614 
615  // Add a raw lua function to this object's method table
616  // For e.g. static member functions
617  Self &AddFunction(const char *name, lua_CFunction func)
618  {
620 
621  lua_pushcfunction(m_lua, func);
622  if (m_protected)
623  lua_pushcclosure(m_lua, secure_trampoline, 1);
624 
625  lua_setfield(m_lua, -2, name);
626  lua_pop(m_lua, 1);
627  return *this;
628  }
629 
630  // Magic to allow binding a const function to Lua. Take care to ensure that you do not
631  // push a const object to lua, or this code will become undefined behavior.
632  template <typename Rt, typename... Args>
634  {
635  return AddMeta(name, reinterpret_cast<member_function<T, Rt, Args...>>(fn));
636  }
637 
638  // Bind a member function to Lua as a metamethod.
639  // Parameters will automatically be pulled from Lua and be passed to the function.
640  // It is the responsiblity of the programmer to ensure a valid LuaPull implementation
641  // is available for each parameter's time.
642  // If the function has a non-void return type, its return value will automatically be
643  // pushed to Lua.
644  template <typename Rt, typename... Args>
646  {
647  lua_State *L = m_lua;
648 
649  lua_pushstring(L, (m_typeName + "." + name).c_str());
650  PushPointerToMember(L, fn);
651  lua_pushcclosure(L, &member_fn_wrapper_<T, Rt, Args...>, 2);
652  if (m_protected)
653  lua_pushcclosure(L, &secure_trampoline, 1);
654 
655  lua_setfield(L, m_index, name);
656 
657  return *this;
658  }
659 
660  // Bind a free function to Lua as a metamethod.
661  // The self parameter will be automatically provided, but the function
662  // is responsible for pulling the rest of its parameters and pushing the
663  // appropriate number of return values.
664  Self &AddMeta(const char *name, member_cfunction<T> fn)
665  {
666  lua_State *L = m_lua;
667 
668  lua_pushstring(L, (m_typeName + "." + name).c_str());
669  PushFreeFunction(L, fn);
670  lua_pushcclosure(L, &member_cfn_wrapper_<T>, 2);
671  if (m_protected)
672  lua_pushcclosure(L, &secure_trampoline, 1);
673 
674  lua_setfield(L, m_index, name);
675 
676  return *this;
677  }
678 
679  // Add a raw lua function to this object's metamethod table
680  Self &AddMeta(const char *name, lua_CFunction func)
681  {
682  lua_pushcfunction(m_lua, func);
683  if (m_protected)
684  lua_pushcclosure(m_lua, secure_trampoline, 1);
685 
686  lua_setfield(m_lua, m_index, name);
687 
688  return *this;
689  }
690 
691  Self &RegisterFuncs(const luaL_Reg *functions)
692  {
693  lua_State *L = m_lua;
695 
696  for (const luaL_Reg *func = functions; func->name; ++func) {
697  lua_pushcfunction(L, func->func);
698  if (m_protected)
699  lua_pushcclosure(L, secure_trampoline, 1);
700 
701  lua_setfield(L, -2, func->name);
702  }
703 
704  lua_pop(L, 1);
705  }
706 
707  Self &AddCallCtor(lua_CFunction func)
708  {
710  lua_getmetatable(m_lua, -1);
711 
712  lua_pushcfunction(m_lua, func);
713  if (m_protected)
714  lua_pushcclosure(m_lua, secure_trampoline, 1);
715 
716  lua_setfield(m_lua, -2, "__call");
717  lua_pop(m_lua, 2);
718 
719  return *this;
720  }
721 
722  Self &AddNewCtor(lua_CFunction func)
723  {
725 
726  lua_pushcfunction(m_lua, func);
727  if (m_protected)
728  lua_pushcclosure(m_lua, secure_trampoline, 1);
729 
730  lua_setfield(m_lua, -2, "New");
731  lua_pop(m_lua, 1);
732  return *this;
733  }
734 
735 private:
736  bool m_protected = false;
737 };
Ret pi_lua_multiple_call(lua_State *l, int index, Ret(*fn)())
Definition: LuaCall.h:19
int secure_trampoline(lua_State *l)
Definition: Sandbox.cpp:441
Definition: LuaMetaType.h:44
Rt(T::*)(Args...) const const_member_function
Definition: LuaMetaType.h:222
static T PullFreeFunction(lua_State *L, int index)
Definition: LuaMetaType.h:315
void StopRecording()
Definition: LuaMetaType.h:78
Dt T::* member_pointer
Definition: LuaMetaType.h:144
const char * GetTypeName() const
Definition: LuaMetaType.h:53
static int getter_member_cfn_wrapper_(lua_State *L)
Definition: LuaMetaType.h:191
Rt(*)(Args...) free_function
Definition: LuaMetaType.h:107
static void PushPointerToMember(lua_State *L, MemT obj)
Definition: LuaMetaType.h:296
static std::enable_if< std::is_same< Rt, void >::value, int >::type free_fn_wrapper_(lua_State *L)
Definition: LuaMetaType.h:126
static void GetNames(std::vector< std::string > &names, const std::string &prefix="", bool methodsOnly=false)
Definition: LuaMetaType.cpp:261
static std::enable_if< std::is_same< Rt, void >::value, int >::type member_fn_wrapper_(lua_State *L)
Definition: LuaMetaType.h:246
static void PushFreeFunction(lua_State *L, T obj)
Definition: LuaMetaType.h:308
std::string m_typeName
Definition: LuaMetaType.h:332
lua_State * m_lua
Definition: LuaMetaType.h:335
int m_ref
Definition: LuaMetaType.h:337
int(*)(lua_State *, T *) member_cfunction
Definition: LuaMetaType.h:173
static std::enable_if<!std::is_same< Rt, void >::value, int >::type member_fn_wrapper_(lua_State *L)
Definition: LuaMetaType.h:226
std::string m_parent
Definition: LuaMetaType.h:333
void StartRecording()
Definition: LuaMetaType.h:68
static std::enable_if<!std::is_same< Rt, void >::value, int >::type free_fn_wrapper_(lua_State *L)
Definition: LuaMetaType.h:111
const char * GetParent() const
Definition: LuaMetaType.h:55
void GetMetatable() const
Definition: LuaMetaType.cpp:386
LuaMetaTypeBase(const char *name)
Definition: LuaMetaType.h:46
static MemT & PullPointerToMember(lua_State *L, int idx)
Definition: LuaMetaType.h:302
static bool GetMetatableFromName(lua_State *l, const char *name)
Definition: LuaMetaType.cpp:373
Rt(T::*)(Args...) member_function
Definition: LuaMetaType.h:219
void SetParent(const char *parent)
Definition: LuaMetaType.h:57
static int member_cfn_wrapper_(lua_State *L)
Definition: LuaMetaType.h:176
static int getter_member_fn_wrapper_(lua_State *L)
Definition: LuaMetaType.h:265
void GetMethodTable(lua_State *L, int index)
Definition: LuaMetaType.h:327
static void * TestUserdata(lua_State *l, int index, const char *name)
Definition: LuaMetaType.cpp:399
void GetAttrTable(lua_State *L, int index)
Definition: LuaMetaType.h:321
static int member_wrapper_(lua_State *L)
Definition: LuaMetaType.h:147
static void * CheckUserdata(lua_State *l, int index, const char *name)
Definition: LuaMetaType.cpp:412
void CreateMetaType(lua_State *l)
Definition: LuaMetaType.cpp:423
int m_index
Definition: LuaMetaType.h:339
bool IsValid() const
Definition: LuaMetaType.h:63
Definition: LuaMetaType.h:342
Self & StopRecording()
Definition: LuaMetaType.h:356
Self & StartRecording()
Definition: LuaMetaType.h:350
Self & AddMeta(const char *name, free_function< Rt, Args... > func)
Definition: LuaMetaType.h:422
LuaMetaTypeGeneric(const char *name)
Definition: LuaMetaType.h:346
Self & SetProtected(bool enabled)
Definition: LuaMetaType.h:362
Self & AddFunction(const char *name, free_function< Rt, Args... > func)
Definition: LuaMetaType.h:395
Self & AddMember(const char *name, lua_CFunction getter)
Definition: LuaMetaType.h:368
Self & AddMeta(const char *name, lua_CFunction func)
Definition: LuaMetaType.h:410
Self & AddFunction(const char *name, lua_CFunction func)
Definition: LuaMetaType.h:381
Self & AddNewCtor(lua_CFunction func)
Definition: LuaMetaType.h:450
Self & AddCallCtor(lua_CFunction func)
Definition: LuaMetaType.h:435
Definition: LuaMetaType.h:468
LuaMetaType(const char *name)
Definition: LuaMetaType.h:472
Self & StopRecording()
Definition: LuaMetaType.h:482
Self & AddMeta(const char *name, member_function< T, Rt, Args... > fn)
Definition: LuaMetaType.h:645
Self & AddMeta(const char *name, member_cfunction< T > fn)
Definition: LuaMetaType.h:664
Self & AddFunction(const char *name, member_cfunction< T > fn)
Definition: LuaMetaType.h:598
Self & AddMeta(const char *name, lua_CFunction func)
Definition: LuaMetaType.h:680
Self & AddMeta(const char *name, const_member_function< T, Rt, Args... > fn)
Definition: LuaMetaType.h:633
Self & AddFunction(const char *name, lua_CFunction func)
Definition: LuaMetaType.h:617
Self & AddFunction(const char *name, const_member_function< T, Rt, Args... > fn)
Definition: LuaMetaType.h:565
Self & AddMember(const char *name, const_member_function< T, Dt > getter, member_function< T, void, Dt2 > setter=nullptr)
Definition: LuaMetaType.h:536
Self & AddMember(const char *name, member_cfunction< T > getter, member_cfunction< T > setter=nullptr)
Definition: LuaMetaType.h:515
Self & AddCallCtor(lua_CFunction func)
Definition: LuaMetaType.h:707
Self & AddMember(const char *name, member_function< T, Dt > getter, member_function< T, void, Dt2 > setter=nullptr)
Definition: LuaMetaType.h:544
Self & RegisterFuncs(const luaL_Reg *functions)
Definition: LuaMetaType.h:691
Self & AddFunction(const char *name, member_function< T, Rt, Args... > fn)
Definition: LuaMetaType.h:577
Self & AddNewCtor(lua_CFunction func)
Definition: LuaMetaType.h:722
Self & StartRecording()
Definition: LuaMetaType.h:476
void SetProtected(bool enabled)
Definition: LuaMetaType.h:490
Self & AddMember(const char *name, member_pointer< T, Dt > t)
Definition: LuaMetaType.h:496