LuaCallWrapper.h 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. /*
  2. * LuaCallWrapper.h, part of VCMI engine
  3. *
  4. * Authors: listed in file AUTHORS in main folder
  5. *
  6. * License: GNU General Public License v2.0 or later
  7. * Full text of license available in license.txt file, in main folder
  8. *
  9. */
  10. #pragma once
  11. #include "api/Registry.h"
  12. #include "LuaStack.h"
  13. #include <type_traits>
  14. VCMI_LIB_NAMESPACE_BEGIN
  15. namespace scripting
  16. {
  17. namespace detail
  18. {
  19. template<int ...>
  20. struct Seq {};
  21. template<int N, int ...S>
  22. struct Gens : Gens<N-1, N-1, S...> {};
  23. template<int ...S>
  24. struct Gens<0, S...>
  25. {
  26. typedef Seq<S...> type;
  27. };
  28. template <typename R, typename ... Args>
  29. class LuaArgumentsTuple
  30. {
  31. public:
  32. using TupleData = std::tuple<Args ...>;
  33. using Functor = R(*)(Args ...);
  34. TupleData args;
  35. Functor f;
  36. LuaArgumentsTuple(Functor _f)
  37. :f(_f),
  38. args()
  39. {
  40. }
  41. STRONG_INLINE int invoke(lua_State * L)
  42. {
  43. return callFunc(L, typename Gens<sizeof...(Args)>::type());
  44. }
  45. private:
  46. template<int ...N>
  47. int callFunc(lua_State * L, Seq<N...>)
  48. {
  49. LuaStack S(L);
  50. bool ok[sizeof...(Args)] = {(S.tryGet(N+1, std::get<N>(args)))...};
  51. if(std::count(std::begin(ok), std::end(ok), false) > 0)
  52. return S.retVoid();
  53. R ret = f(std::get<N>(args) ...);
  54. S.clear();
  55. S.push(ret);
  56. return 1;
  57. }
  58. };
  59. class LuaFunctionInvoker
  60. {
  61. public:
  62. template<typename R, typename ... Args>
  63. static STRONG_INLINE int invoke(lua_State * L, R(*f)(Args ...))
  64. {
  65. LuaArgumentsTuple<R, Args ...> args(f);
  66. return args.invoke(L);
  67. }
  68. };
  69. }
  70. template <typename F, F f>
  71. class LuaFunctionWrapper
  72. {
  73. public:
  74. static int invoke(lua_State * L)
  75. {
  76. return detail::LuaFunctionInvoker::invoke(L, f);
  77. }
  78. };
  79. //TODO: this should be the only one wrapper type
  80. //
  81. template <typename U, typename M, M m>
  82. class LuaMethodWrapper
  83. {
  84. };
  85. template <typename U, typename T, typename R, R(T:: * method)()const>
  86. class LuaMethodWrapper <U, R(T:: *)()const, method>
  87. {
  88. public:
  89. static int invoke(lua_State * L)
  90. {
  91. LuaStack S(L);
  92. const U * obj = nullptr;
  93. if(!S.tryGet(1,obj))
  94. return S.retVoid();
  95. static auto functor = std::mem_fn(method);
  96. S.clear();
  97. S.push(functor(obj));
  98. return S.retPushed();
  99. }
  100. };
  101. template <typename U, typename T, typename R, R(T:: * method)()>
  102. class LuaMethodWrapper <U, R(T:: *)(), method>
  103. {
  104. public:
  105. static int invoke(lua_State * L)
  106. {
  107. LuaStack S(L);
  108. U * obj = nullptr;
  109. if(!S.tryGet(1,obj))
  110. return S.retVoid();
  111. static auto functor = std::mem_fn(method);
  112. S.clear();
  113. S.push(functor(obj));
  114. return S.retPushed();
  115. }
  116. };
  117. template <typename U, typename T, void(T:: * method)()const>
  118. class LuaMethodWrapper <U, void(T:: *)()const, method>
  119. {
  120. public:
  121. static int invoke(lua_State * L)
  122. {
  123. LuaStack S(L);
  124. const U * obj = nullptr;
  125. if(!S.tryGet(1,obj))
  126. return S.retVoid();
  127. static auto functor = std::mem_fn(method);
  128. S.clear();
  129. functor(obj);
  130. return 0;
  131. }
  132. };
  133. template <typename U, typename T, void(T:: * method)()>
  134. class LuaMethodWrapper <U, void(T:: *)(), method>
  135. {
  136. public:
  137. static int invoke(lua_State * L)
  138. {
  139. LuaStack S(L);
  140. U * obj = nullptr;
  141. if(!S.tryGet(1,obj))
  142. return S.retVoid();
  143. static auto functor = std::mem_fn(method);
  144. S.clear();
  145. functor(obj);
  146. return 0;
  147. }
  148. };
  149. template <typename U, typename T, typename R, typename P1, R(T:: * method)(P1)const>
  150. class LuaMethodWrapper <U, R(T:: *)(P1)const, method>
  151. {
  152. using PM1 = std::remove_cv_t<std::remove_reference_t<P1>>;
  153. public:
  154. static int invoke(lua_State * L)
  155. {
  156. LuaStack S(L);
  157. const U * obj = nullptr;
  158. if(!S.tryGet(1,obj))
  159. return S.retVoid();
  160. PM1 p1;
  161. if(!S.tryGet(2, p1))
  162. return S.retVoid();
  163. static auto functor = std::mem_fn(method);
  164. S.clear();
  165. S.push(functor(obj, p1));
  166. return S.retPushed();
  167. }
  168. };
  169. template <typename U, typename T, typename R, typename P1, R(T:: * method)(P1)>
  170. class LuaMethodWrapper <U, R(T:: *)(P1), method>
  171. {
  172. using PM1 = std::remove_cv_t<std::remove_reference_t<P1>>;
  173. public:
  174. static int invoke(lua_State * L)
  175. {
  176. LuaStack S(L);
  177. U * obj = nullptr;
  178. if(!S.tryGet(1,obj))
  179. return S.retVoid();
  180. PM1 p1;
  181. if(!S.tryGet(2, p1))
  182. return S.retVoid();
  183. static auto functor = std::mem_fn(method);
  184. S.clear();
  185. S.push(functor(obj, p1));
  186. return S.retPushed();
  187. }
  188. };
  189. template <typename U, typename T, typename P1, void(T:: * method)(P1)const>
  190. class LuaMethodWrapper <U, void(T:: *)(P1)const, method>
  191. {
  192. using PM1 = std::remove_cv_t<std::remove_reference_t<P1>>;
  193. public:
  194. static int invoke(lua_State * L)
  195. {
  196. LuaStack S(L);
  197. const U * obj = nullptr;
  198. if(!S.tryGet(1,obj))
  199. return S.retVoid();
  200. PM1 p1;
  201. if(!S.tryGet(2, p1))
  202. return S.retVoid();
  203. static auto functor = std::mem_fn(method);
  204. S.clear();
  205. functor(obj, p1);
  206. return 0;
  207. }
  208. };
  209. template <typename U, typename T, typename P1, void(T:: * method)(P1)>
  210. class LuaMethodWrapper <U, void(T:: *)(P1), method>
  211. {
  212. using PM1 = std::remove_cv_t<std::remove_reference_t<P1>>;
  213. public:
  214. static int invoke(lua_State * L)
  215. {
  216. LuaStack S(L);
  217. U * obj = nullptr;
  218. if(!S.tryGet(1,obj))
  219. return S.retVoid();
  220. PM1 p1;
  221. if(!S.tryGet(2, p1))
  222. return S.retVoid();
  223. static auto functor = std::mem_fn(method);
  224. S.clear();
  225. functor(obj, p1);
  226. return 0;
  227. }
  228. };
  229. template <typename U, typename T, typename R, typename P1, typename P2, R(T:: * method)(P1, P2)const>
  230. class LuaMethodWrapper <U, R(T:: *)(P1, P2)const, method>
  231. {
  232. using PM1 = std::remove_cv_t<std::remove_reference_t<P1>>;
  233. using PM2 = std::remove_cv_t<std::remove_reference_t<P2>>;
  234. public:
  235. static int invoke(lua_State * L)
  236. {
  237. LuaStack S(L);
  238. const U * obj = nullptr;
  239. if(!S.tryGet(1, obj))
  240. return S.retVoid();
  241. PM1 p1;
  242. if(!S.tryGet(2, p1))
  243. return S.retVoid();
  244. PM2 p2;
  245. if(!S.tryGet(3, p2))
  246. return S.retVoid();
  247. static auto functor = std::mem_fn(method);
  248. S.clear();
  249. S.push(functor(obj, p1, p2));
  250. return S.retPushed();
  251. }
  252. };
  253. template <typename U, typename T, typename P1, typename P2, void(T:: * method)(P1, P2)const>
  254. class LuaMethodWrapper <U, void(T:: *)(P1, P2)const, method>
  255. {
  256. using PM1 = std::remove_cv_t<std::remove_reference_t<P1>>;
  257. using PM2 = std::remove_cv_t<std::remove_reference_t<P2>>;
  258. public:
  259. static int invoke(lua_State * L)
  260. {
  261. LuaStack S(L);
  262. const U * obj = nullptr;
  263. if(!S.tryGet(1, obj))
  264. return S.retVoid();
  265. PM1 p1;
  266. if(!S.tryGet(2, p1))
  267. return S.retVoid();
  268. PM2 p2;
  269. if(!S.tryGet(3, p2))
  270. return S.retVoid();
  271. static auto functor = std::mem_fn(method);
  272. S.clear();
  273. functor(obj, p1, p2);
  274. return 0;
  275. }
  276. };
  277. }
  278. VCMI_LIB_NAMESPACE_END