function_types.hpp 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769
  1. // sol2
  2. // The MIT License (MIT)
  3. // Copyright (c) 2013-2022 Rapptz, ThePhD and contributors
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy of
  5. // this software and associated documentation files (the "Software"), to deal in
  6. // the Software without restriction, including without limitation the rights to
  7. // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  8. // the Software, and to permit persons to whom the Software is furnished to do so,
  9. // subject to the following conditions:
  10. // The above copyright notice and this permission notice shall be included in all
  11. // copies or substantial portions of the Software.
  12. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  13. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  14. // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  15. // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  16. // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  17. // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  18. #ifndef SOL_FUNCTION_TYPES_HPP
  19. #define SOL_FUNCTION_TYPES_HPP
  20. #include <sol/function_types_core.hpp>
  21. #include <sol/function_types_templated.hpp>
  22. #include <sol/function_types_stateless.hpp>
  23. #include <sol/function_types_stateful.hpp>
  24. #include <sol/function_types_overloaded.hpp>
  25. #include <sol/resolve.hpp>
  26. #include <sol/call.hpp>
  27. namespace sol {
  28. namespace function_detail {
  29. template <typename T>
  30. struct class_indicator {
  31. using type = T;
  32. };
  33. struct call_indicator { };
  34. template <bool yielding>
  35. int lua_c_wrapper(lua_State* L) {
  36. lua_CFunction cf = lua_tocfunction(L, lua_upvalueindex(2));
  37. int nr = cf(L);
  38. if constexpr (yielding) {
  39. return lua_yield(L, nr);
  40. }
  41. else {
  42. return nr;
  43. }
  44. }
  45. template <bool yielding>
  46. int lua_c_noexcept_wrapper(lua_State* L) noexcept {
  47. detail::lua_CFunction_noexcept cf = reinterpret_cast<detail::lua_CFunction_noexcept>(lua_tocfunction(L, lua_upvalueindex(2)));
  48. int nr = cf(L);
  49. if constexpr (yielding) {
  50. return lua_yield(L, nr);
  51. }
  52. else {
  53. return nr;
  54. }
  55. }
  56. struct c_function_invocation { };
  57. template <bool is_yielding, bool no_trampoline, typename Fx, typename... Args>
  58. void select(lua_State* L, Fx&& fx, Args&&... args);
  59. template <bool is_yielding, bool no_trampoline, typename Fx, typename... Args>
  60. void select_set_fx(lua_State* L, Args&&... args) {
  61. lua_CFunction freefunc = no_trampoline ? function_detail::call<meta::unqualified_t<Fx>, 2, is_yielding>
  62. : detail::static_trampoline<function_detail::call<meta::unqualified_t<Fx>, 2, is_yielding>>;
  63. int upvalues = 0;
  64. upvalues += stack::push(L, nullptr);
  65. upvalues += stack::push<user<Fx>>(L, std::forward<Args>(args)...);
  66. stack::push(L, c_closure(freefunc, upvalues));
  67. }
  68. template <bool is_yielding, bool no_trampoline, typename R, typename... A, typename Fx, typename... Args>
  69. void select_convertible(types<R(A...)>, lua_State* L, Fx&& fx, Args&&... args) {
  70. using dFx = std::decay_t<meta::unwrap_unqualified_t<Fx>>;
  71. using fx_ptr_t = R (*)(A...);
  72. constexpr bool is_convertible = std::is_convertible_v<dFx, fx_ptr_t>;
  73. if constexpr (is_convertible) {
  74. fx_ptr_t fxptr = detail::unwrap(std::forward<Fx>(fx));
  75. select<is_yielding, no_trampoline>(L, std::move(fxptr), std::forward<Args>(args)...);
  76. }
  77. else {
  78. using F = function_detail::functor_function<dFx, false, true>;
  79. select_set_fx<is_yielding, no_trampoline, F>(L, std::forward<Fx>(fx), std::forward<Args>(args)...);
  80. }
  81. }
  82. template <bool is_yielding, bool no_trampoline, typename Fx, typename... Args>
  83. void select_convertible(types<>, lua_State* L, Fx&& fx, Args&&... args) {
  84. typedef meta::function_signature_t<meta::unwrap_unqualified_t<Fx>> Sig;
  85. select_convertible<is_yielding, no_trampoline>(types<Sig>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...);
  86. }
  87. template <bool is_yielding, bool no_trampoline, typename Fx, typename... Args>
  88. void select_member_variable(lua_State* L, Fx&& fx, Args&&... args) {
  89. using uFx = meta::unqualified_t<Fx>;
  90. if constexpr (sizeof...(Args) < 1) {
  91. using C = typename meta::bind_traits<uFx>::object_type;
  92. lua_CFunction freefunc = &function_detail::upvalue_this_member_variable<C, Fx>::template call<is_yielding, no_trampoline>;
  93. int upvalues = 0;
  94. upvalues += stack::push(L, nullptr);
  95. upvalues += stack::stack_detail::push_as_upvalues(L, fx);
  96. stack::push(L, c_closure(freefunc, upvalues));
  97. }
  98. else if constexpr (sizeof...(Args) < 2) {
  99. using Tu = typename meta::meta_detail::unqualified_non_alias<Args...>::type;
  100. constexpr bool is_reference = meta::is_specialization_of_v<Tu, std::reference_wrapper> || std::is_pointer_v<Tu>;
  101. if constexpr (meta::is_specialization_of_v<Tu, function_detail::class_indicator>) {
  102. lua_CFunction freefunc
  103. = &function_detail::upvalue_this_member_variable<typename Tu::type, Fx>::template call<is_yielding, no_trampoline>;
  104. int upvalues = 0;
  105. upvalues += stack::push(L, nullptr);
  106. upvalues += stack::stack_detail::push_as_upvalues(L, fx);
  107. stack::push(L, c_closure(freefunc, upvalues));
  108. }
  109. else if constexpr (is_reference) {
  110. typedef std::decay_t<Fx> dFx;
  111. dFx memfxptr(std::forward<Fx>(fx));
  112. auto userptr = detail::ptr(std::forward<Args>(args)...);
  113. lua_CFunction freefunc = &function_detail::upvalue_member_variable<std::decay_t<decltype(*userptr)>,
  114. meta::unqualified_t<Fx>>::template call<is_yielding, no_trampoline>;
  115. int upvalues = 0;
  116. upvalues += stack::push(L, nullptr);
  117. upvalues += stack::stack_detail::push_as_upvalues(L, memfxptr);
  118. upvalues += stack::push(L, static_cast<void const*>(userptr));
  119. stack::push(L, c_closure(freefunc, upvalues));
  120. }
  121. else {
  122. using clean_fx = std::remove_pointer_t<std::decay_t<Fx>>;
  123. using F = function_detail::member_variable<Tu, clean_fx, is_yielding, no_trampoline>;
  124. select_set_fx<is_yielding, no_trampoline, F>(L, std::forward<Fx>(fx), std::forward<Args>(args)...);
  125. }
  126. }
  127. else {
  128. using C = typename meta::bind_traits<uFx>::object_type;
  129. using clean_fx = std::remove_pointer_t<std::decay_t<Fx>>;
  130. using F = function_detail::member_variable<C, clean_fx, is_yielding, no_trampoline>;
  131. select_set_fx<is_yielding, no_trampoline, F>(L, std::forward<Fx>(fx), std::forward<Args>(args)...);
  132. }
  133. }
  134. template <bool is_yielding, bool no_trampoline, typename Fx, typename T, typename... Args>
  135. void select_member_function_with(lua_State* L, Fx&& fx, T&& obj, Args&&... args) {
  136. using dFx = std::decay_t<Fx>;
  137. using Tu = meta::unqualified_t<T>;
  138. if constexpr (meta::is_specialization_of_v<Tu, function_detail::class_indicator>) {
  139. (void)obj;
  140. using C = typename Tu::type;
  141. lua_CFunction freefunc = &function_detail::upvalue_this_member_function<C, dFx>::template call<is_yielding, no_trampoline>;
  142. int upvalues = 0;
  143. upvalues += stack::push(L, nullptr);
  144. upvalues += stack::push<user<dFx>>(L, std::forward<Fx>(fx), std::forward<Args>(args)...);
  145. stack::push(L, c_closure(freefunc, upvalues));
  146. }
  147. else {
  148. constexpr bool is_reference = meta::is_specialization_of_v<Tu, std::reference_wrapper> || std::is_pointer_v<Tu>;
  149. if constexpr (is_reference) {
  150. auto userptr = detail::ptr(std::forward<T>(obj));
  151. lua_CFunction freefunc
  152. = &function_detail::upvalue_member_function<std::decay_t<decltype(*userptr)>, dFx>::template call<is_yielding, no_trampoline>;
  153. int upvalues = 0;
  154. upvalues += stack::push(L, nullptr);
  155. upvalues += stack::push<user<dFx>>(L, std::forward<Fx>(fx), std::forward<Args>(args)...);
  156. upvalues += stack::push(L, lightuserdata_value(static_cast<void*>(userptr)));
  157. stack::push(L, c_closure(freefunc, upvalues));
  158. }
  159. else {
  160. using F = function_detail::member_function<Tu, dFx, is_yielding, no_trampoline>;
  161. select_set_fx<is_yielding, no_trampoline, F>(L, std::forward<Fx>(fx), std::forward<T>(obj), std::forward<Args>(args)...);
  162. }
  163. }
  164. }
  165. template <bool is_yielding, bool no_trampoline, typename Fx, typename... Args>
  166. void select_member_function(lua_State* L, Fx&& fx, Args&&... args) {
  167. using dFx = std::decay_t<Fx>;
  168. if constexpr (sizeof...(Args) < 1) {
  169. using C = typename meta::bind_traits<meta::unqualified_t<Fx>>::object_type;
  170. lua_CFunction freefunc = &function_detail::upvalue_this_member_function<C, dFx>::template call<is_yielding, no_trampoline>;
  171. int upvalues = 0;
  172. upvalues += stack::push(L, nullptr);
  173. upvalues += stack::push<user<dFx>>(L, std::forward<Fx>(fx));
  174. stack::push(L, c_closure(freefunc, upvalues));
  175. }
  176. else {
  177. select_member_function_with<is_yielding, no_trampoline>(L, std::forward<Fx>(fx), std::forward<Args>(args)...);
  178. }
  179. }
  180. template <bool is_yielding, bool no_trampoline, typename Fx, typename... Args>
  181. void select(lua_State* L, Fx&& fx, Args&&... args) {
  182. using uFx = meta::unqualified_t<Fx>;
  183. if constexpr (is_lua_reference_v<uFx>) {
  184. // TODO: hoist into lambda in this case for yielding???
  185. stack::push(L, std::forward<Fx>(fx), std::forward<Args>(args)...);
  186. }
  187. else if constexpr (is_lua_c_function_v<uFx>) {
  188. if constexpr (no_trampoline) {
  189. if (is_yielding) {
  190. int upvalues = 0;
  191. upvalues += stack::push(L, nullptr);
  192. upvalues += stack::push(L, std::forward<Fx>(fx));
  193. #if SOL_IS_ON(SOL_USE_NOEXCEPT_FUNCTION_TYPE)
  194. if constexpr (std::is_nothrow_invocable_r_v<int, uFx, lua_State*>) {
  195. detail::lua_CFunction_noexcept cf = &lua_c_noexcept_wrapper<true>;
  196. lua_pushcclosure(L, reinterpret_cast<lua_CFunction>(cf), upvalues);
  197. }
  198. else
  199. #endif
  200. {
  201. lua_CFunction cf = &function_detail::lua_c_wrapper<true>;
  202. lua_pushcclosure(L, cf, upvalues);
  203. }
  204. }
  205. else {
  206. lua_pushcclosure(L, std::forward<Fx>(fx), 0);
  207. }
  208. }
  209. else {
  210. int upvalues = 0;
  211. upvalues += stack::push(L, nullptr);
  212. upvalues += stack::push(L, std::forward<Fx>(fx));
  213. #if SOL_IS_ON(SOL_USE_NOEXCEPT_FUNCTION_TYPE)
  214. if constexpr (std::is_nothrow_invocable_r_v<int, uFx, lua_State*>) {
  215. detail::lua_CFunction_noexcept cf = &lua_c_noexcept_wrapper<is_yielding>;
  216. lua_pushcclosure(L, reinterpret_cast<lua_CFunction>(cf), upvalues);
  217. }
  218. else {
  219. lua_CFunction cf = &function_detail::lua_c_wrapper<is_yielding>;
  220. lua_pushcclosure(L, cf, upvalues);
  221. }
  222. #else
  223. lua_CFunction cf = &function_detail::lua_c_wrapper<is_yielding>;
  224. lua_pushcclosure(L, cf, upvalues);
  225. #endif
  226. }
  227. }
  228. else if constexpr (std::is_function_v<std::remove_pointer_t<uFx>>) {
  229. std::decay_t<Fx> target(std::forward<Fx>(fx), std::forward<Args>(args)...);
  230. lua_CFunction freefunc = &function_detail::upvalue_free_function<Fx>::template call<is_yielding, no_trampoline>;
  231. int upvalues = 0;
  232. upvalues += stack::push(L, nullptr);
  233. upvalues += stack::stack_detail::push_as_upvalues(L, target);
  234. stack::push(L, c_closure(freefunc, upvalues));
  235. }
  236. else if constexpr (std::is_member_function_pointer_v<uFx>) {
  237. select_member_function<is_yielding, no_trampoline>(L, std::forward<Fx>(fx), std::forward<Args>(args)...);
  238. }
  239. else if constexpr (meta::is_member_object_v<uFx>) {
  240. select_member_variable<is_yielding, no_trampoline>(L, std::forward<Fx>(fx), std::forward<Args>(args)...);
  241. }
  242. else {
  243. select_convertible<is_yielding, no_trampoline>(types<>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...);
  244. }
  245. }
  246. } // namespace function_detail
  247. namespace stack {
  248. template <typename... Sigs>
  249. struct unqualified_pusher<function_sig<Sigs...>> {
  250. template <bool is_yielding, typename Arg0, typename... Args>
  251. static int push_yielding(lua_State* L, Arg0&& arg0, Args&&... args) {
  252. if constexpr (meta::is_specialization_of_v<meta::unqualified_t<Arg0>, std::function>) {
  253. if constexpr (is_yielding) {
  254. return stack::push<meta::unqualified_t<Arg0>>(L, detail::yield_tag, std::forward<Arg0>(arg0), std::forward<Args>(args)...);
  255. }
  256. else {
  257. return stack::push(L, std::forward<Arg0>(arg0), std::forward<Args>(args)...);
  258. }
  259. }
  260. else {
  261. function_detail::select<is_yielding, false>(L, std::forward<Arg0>(arg0), std::forward<Args>(args)...);
  262. return 1;
  263. }
  264. }
  265. template <typename Arg0, typename... Args>
  266. static int push(lua_State* L, Arg0&& arg0, Args&&... args) {
  267. if constexpr (std::is_same_v<meta::unqualified_t<Arg0>, detail::yield_tag_t>) {
  268. push_yielding<true>(L, std::forward<Args>(args)...);
  269. }
  270. else if constexpr (meta::is_specialization_of_v<meta::unqualified_t<Arg0>, yielding_t>) {
  271. push_yielding<true>(L, std::forward<Arg0>(arg0).func, std::forward<Args>(args)...);
  272. }
  273. else {
  274. push_yielding<false>(L, std::forward<Arg0>(arg0), std::forward<Args>(args)...);
  275. }
  276. return 1;
  277. }
  278. };
  279. template <typename T>
  280. struct unqualified_pusher<yielding_t<T>> {
  281. template <typename... Args>
  282. static int push(lua_State* L, const yielding_t<T>& f, Args&&... args) {
  283. if constexpr (meta::is_specialization_of_v<meta::unqualified_t<T>, std::function>) {
  284. return stack::push<T>(L, detail::yield_tag, f.func, std::forward<Args>(args)...);
  285. }
  286. else {
  287. function_detail::select<true, false>(L, f.func, std::forward<Args>(args)...);
  288. return 1;
  289. }
  290. }
  291. template <typename... Args>
  292. static int push(lua_State* L, yielding_t<T>&& f, Args&&... args) {
  293. if constexpr (meta::is_specialization_of_v<meta::unqualified_t<T>, std::function>) {
  294. return stack::push<T>(L, detail::yield_tag, std::move(f.func), std::forward<Args>(args)...);
  295. }
  296. else {
  297. function_detail::select<true, false>(L, std::move(f.func), std::forward<Args>(args)...);
  298. return 1;
  299. }
  300. }
  301. };
  302. template <typename T, typename... Args>
  303. struct unqualified_pusher<function_arguments<T, Args...>> {
  304. template <std::size_t... I, typename FP>
  305. static int push_func(std::index_sequence<I...>, lua_State* L, FP&& fp) {
  306. return stack::push<T>(L, std::get<I>(std::forward<FP>(fp).arguments)...);
  307. }
  308. static int push(lua_State* L, const function_arguments<T, Args...>& fp) {
  309. return push_func(std::make_index_sequence<sizeof...(Args)>(), L, fp);
  310. }
  311. static int push(lua_State* L, function_arguments<T, Args...>&& fp) {
  312. return push_func(std::make_index_sequence<sizeof...(Args)>(), L, std::move(fp));
  313. }
  314. };
  315. template <typename Signature>
  316. struct unqualified_pusher<std::function<Signature>> {
  317. using TargetFunctor = function_detail::functor_function<std::function<Signature>, false, true>;
  318. static int push(lua_State* L, detail::yield_tag_t, const std::function<Signature>& fx) {
  319. if (fx) {
  320. function_detail::select_set_fx<true, false, TargetFunctor>(L, fx);
  321. return 1;
  322. }
  323. return stack::push(L, lua_nil);
  324. }
  325. static int push(lua_State* L, detail::yield_tag_t, std::function<Signature>&& fx) {
  326. if (fx) {
  327. function_detail::select_set_fx<true, false, TargetFunctor>(L, std::move(fx));
  328. return 1;
  329. }
  330. return stack::push(L, lua_nil);
  331. }
  332. static int push(lua_State* L, const std::function<Signature>& fx) {
  333. if (fx) {
  334. function_detail::select_set_fx<false, false, TargetFunctor>(L, fx);
  335. return 1;
  336. }
  337. return stack::push(L, lua_nil);
  338. }
  339. static int push(lua_State* L, std::function<Signature>&& fx) {
  340. if (fx) {
  341. function_detail::select_set_fx<false, false, TargetFunctor>(L, std::move(fx));
  342. return 1;
  343. }
  344. return stack::push(L, lua_nil);
  345. }
  346. };
  347. template <typename Signature>
  348. struct unqualified_pusher<Signature, std::enable_if_t<meta::is_member_object_or_function_v<Signature>>> {
  349. template <typename... Args>
  350. static int push(lua_State* L, Args&&... args) {
  351. function_detail::select<false, false>(L, std::forward<Args>(args)...);
  352. return 1;
  353. }
  354. };
  355. template <typename Signature>
  356. struct unqualified_pusher<Signature,
  357. std::enable_if_t<meta::all<std::is_function<std::remove_pointer_t<Signature>>, meta::neg<std::is_same<Signature, lua_CFunction>>,
  358. meta::neg<std::is_same<Signature, std::remove_pointer_t<lua_CFunction>>>
  359. #if SOL_IS_ON(SOL_USE_NOEXCEPT_FUNCTION_TYPE)
  360. ,
  361. meta::neg<std::is_same<Signature, detail::lua_CFunction_noexcept>>,
  362. meta::neg<std::is_same<Signature, std::remove_pointer_t<detail::lua_CFunction_noexcept>>>
  363. #endif // noexcept function types
  364. >::value>> {
  365. template <typename F>
  366. static int push(lua_State* L, F&& f) {
  367. function_detail::select<false, true>(L, std::forward<F>(f));
  368. return 1;
  369. }
  370. };
  371. template <typename... Functions>
  372. struct unqualified_pusher<overload_set<Functions...>> {
  373. static int push(lua_State* L, overload_set<Functions...>&& set) {
  374. using F = function_detail::overloaded_function<0, Functions...>;
  375. function_detail::select_set_fx<false, false, F>(L, std::move(set.functions));
  376. return 1;
  377. }
  378. static int push(lua_State* L, const overload_set<Functions...>& set) {
  379. using F = function_detail::overloaded_function<0, Functions...>;
  380. function_detail::select_set_fx<false, false, F>(L, set.functions);
  381. return 1;
  382. }
  383. };
  384. template <typename T>
  385. struct unqualified_pusher<protect_t<T>> {
  386. static int push(lua_State* L, protect_t<T>&& pw) {
  387. lua_CFunction cf = call_detail::call_user<void, false, false, protect_t<T>, 2>;
  388. int upvalues = 0;
  389. upvalues += stack::push(L, nullptr);
  390. upvalues += stack::push<user<protect_t<T>>>(L, std::move(pw.value));
  391. return stack::push(L, c_closure(cf, upvalues));
  392. }
  393. static int push(lua_State* L, const protect_t<T>& pw) {
  394. lua_CFunction cf = call_detail::call_user<void, false, false, protect_t<T>, 2>;
  395. int upvalues = 0;
  396. upvalues += stack::push(L, nullptr);
  397. upvalues += stack::push<user<protect_t<T>>>(L, pw.value);
  398. return stack::push(L, c_closure(cf, upvalues));
  399. }
  400. };
  401. template <typename F, typename G>
  402. struct unqualified_pusher<property_wrapper<F, G>> {
  403. static int push(lua_State* L, property_wrapper<F, G>&& pw) {
  404. if constexpr (std::is_void_v<F>) {
  405. return stack::push(L, std::move(pw.write()));
  406. }
  407. else if constexpr (std::is_void_v<G>) {
  408. return stack::push(L, std::move(pw.read()));
  409. }
  410. else {
  411. return stack::push(L, overload(std::move(pw.read()), std::move(pw.write())));
  412. }
  413. }
  414. static int push(lua_State* L, const property_wrapper<F, G>& pw) {
  415. if constexpr (std::is_void_v<F>) {
  416. return stack::push(L, pw.write);
  417. }
  418. else if constexpr (std::is_void_v<G>) {
  419. return stack::push(L, pw.read);
  420. }
  421. else {
  422. return stack::push(L, overload(pw.read, pw.write));
  423. }
  424. }
  425. };
  426. template <typename T>
  427. struct unqualified_pusher<var_wrapper<T>> {
  428. static int push(lua_State* L, var_wrapper<T>&& vw) {
  429. return stack::push(L, std::move(vw.value()));
  430. }
  431. static int push(lua_State* L, const var_wrapper<T>& vw) {
  432. return stack::push(L, vw.value());
  433. }
  434. };
  435. template <typename... Functions>
  436. struct unqualified_pusher<factory_wrapper<Functions...>> {
  437. static int push(lua_State* L, const factory_wrapper<Functions...>& fw) {
  438. using F = function_detail::overloaded_function<0, Functions...>;
  439. function_detail::select_set_fx<false, false, F>(L, fw.functions);
  440. return 1;
  441. }
  442. static int push(lua_State* L, factory_wrapper<Functions...>&& fw) {
  443. using F = function_detail::overloaded_function<0, Functions...>;
  444. function_detail::select_set_fx<false, false, F>(L, std::move(fw.functions));
  445. return 1;
  446. }
  447. static int push(lua_State* L, const factory_wrapper<Functions...>& fw, function_detail::call_indicator) {
  448. using F = function_detail::overloaded_function<1, Functions...>;
  449. function_detail::select_set_fx<false, false, F>(L, fw.functions);
  450. return 1;
  451. }
  452. static int push(lua_State* L, factory_wrapper<Functions...>&& fw, function_detail::call_indicator) {
  453. using F = function_detail::overloaded_function<1, Functions...>;
  454. function_detail::select_set_fx<false, false, F>(L, std::move(fw.functions));
  455. return 1;
  456. }
  457. };
  458. template <>
  459. struct unqualified_pusher<no_construction> {
  460. static int push(lua_State* L, no_construction) {
  461. lua_CFunction cf = &function_detail::no_construction_error;
  462. return stack::push(L, cf);
  463. }
  464. static int push(lua_State* L, no_construction c, function_detail::call_indicator) {
  465. return push(L, c);
  466. }
  467. };
  468. template <typename T>
  469. struct unqualified_pusher<detail::tagged<T, no_construction>> {
  470. static int push(lua_State* L, detail::tagged<T, no_construction>) {
  471. lua_CFunction cf = &function_detail::no_construction_error;
  472. return stack::push(L, cf);
  473. }
  474. static int push(lua_State* L, no_construction, function_detail::call_indicator) {
  475. lua_CFunction cf = &function_detail::no_construction_error;
  476. return stack::push(L, cf);
  477. }
  478. };
  479. template <typename T, typename... Lists>
  480. struct unqualified_pusher<detail::tagged<T, constructor_list<Lists...>>> {
  481. static int push(lua_State* L, detail::tagged<T, constructor_list<Lists...>>) {
  482. lua_CFunction cf = call_detail::construct<T, detail::default_safe_function_calls, true, Lists...>;
  483. return stack::push(L, cf);
  484. }
  485. static int push(lua_State* L, constructor_list<Lists...>) {
  486. lua_CFunction cf = call_detail::construct<T, detail::default_safe_function_calls, true, Lists...>;
  487. return stack::push(L, cf);
  488. }
  489. };
  490. template <typename L0, typename... Lists>
  491. struct unqualified_pusher<constructor_list<L0, Lists...>> {
  492. typedef constructor_list<L0, Lists...> cl_t;
  493. static int push(lua_State* L, cl_t cl) {
  494. typedef typename meta::bind_traits<L0>::return_type T;
  495. return stack::push<detail::tagged<T, cl_t>>(L, cl);
  496. }
  497. };
  498. template <typename T, typename... Fxs>
  499. struct unqualified_pusher<detail::tagged<T, constructor_wrapper<Fxs...>>> {
  500. static int push(lua_State* L, detail::tagged<T, constructor_wrapper<Fxs...>>&& c) {
  501. return push(L, std::move(c.value()));
  502. }
  503. static int push(lua_State* L, const detail::tagged<T, const constructor_wrapper<Fxs...>>& c) {
  504. return push(L, c.value());
  505. }
  506. static int push(lua_State* L, constructor_wrapper<Fxs...>&& c) {
  507. lua_CFunction cf = call_detail::call_user<T, false, false, constructor_wrapper<Fxs...>, 2>;
  508. int upvalues = 0;
  509. upvalues += stack::push(L, nullptr);
  510. upvalues += stack::push<user<constructor_wrapper<Fxs...>>>(L, std::move(c));
  511. return stack::push(L, c_closure(cf, upvalues));
  512. }
  513. static int push(lua_State* L, const constructor_wrapper<Fxs...>& c) {
  514. lua_CFunction cf = call_detail::call_user<T, false, false, constructor_wrapper<Fxs...>, 2>;
  515. int upvalues = 0;
  516. upvalues += stack::push(L, nullptr);
  517. upvalues += stack::push<user<constructor_wrapper<Fxs...>>>(L, c);
  518. return stack::push(L, c_closure(cf, upvalues));
  519. }
  520. };
  521. template <typename F, typename... Fxs>
  522. struct unqualified_pusher<constructor_wrapper<F, Fxs...>> {
  523. static int push(lua_State* L, const constructor_wrapper<F, Fxs...>& c) {
  524. typedef typename meta::bind_traits<F>::template arg_at<0> arg0;
  525. typedef meta::unqualified_t<std::remove_pointer_t<arg0>> T;
  526. return stack::push<detail::tagged<T, constructor_wrapper<F, Fxs...>>>(L, c);
  527. }
  528. static int push(lua_State* L, constructor_wrapper<F, Fxs...>&& c) {
  529. typedef typename meta::bind_traits<F>::template arg_at<0> arg0;
  530. typedef meta::unqualified_t<std::remove_pointer_t<arg0>> T;
  531. return stack::push<detail::tagged<T, constructor_wrapper<F, Fxs...>>>(L, std::move(c));
  532. }
  533. };
  534. template <typename T>
  535. struct unqualified_pusher<detail::tagged<T, destructor_wrapper<void>>> {
  536. static int push(lua_State* L, destructor_wrapper<void>) {
  537. lua_CFunction cf = detail::usertype_alloc_destroy<T>;
  538. return stack::push(L, cf);
  539. }
  540. };
  541. template <typename T, typename Fx>
  542. struct unqualified_pusher<detail::tagged<T, destructor_wrapper<Fx>>> {
  543. static int push(lua_State* L, destructor_wrapper<Fx>&& c) {
  544. lua_CFunction cf = call_detail::call_user<T, false, false, destructor_wrapper<Fx>, 2>;
  545. int upvalues = 0;
  546. upvalues += stack::push(L, nullptr);
  547. upvalues += stack::push<user<destructor_wrapper<Fx>>>(L, std::move(c));
  548. return stack::push(L, c_closure(cf, upvalues));
  549. }
  550. static int push(lua_State* L, const destructor_wrapper<Fx>& c) {
  551. lua_CFunction cf = call_detail::call_user<T, false, false, destructor_wrapper<Fx>, 2>;
  552. int upvalues = 0;
  553. upvalues += stack::push(L, nullptr);
  554. upvalues += stack::push<user<destructor_wrapper<Fx>>>(L, c);
  555. return stack::push(L, c_closure(cf, upvalues));
  556. }
  557. };
  558. template <typename Fx>
  559. struct unqualified_pusher<destructor_wrapper<Fx>> {
  560. static int push(lua_State* L, destructor_wrapper<Fx>&& c) {
  561. lua_CFunction cf = call_detail::call_user<void, false, false, destructor_wrapper<Fx>, 2>;
  562. int upvalues = 0;
  563. upvalues += stack::push(L, nullptr);
  564. upvalues += stack::push<user<destructor_wrapper<Fx>>>(L, std::move(c));
  565. return stack::push(L, c_closure(cf, upvalues));
  566. }
  567. static int push(lua_State* L, const destructor_wrapper<Fx>& c) {
  568. lua_CFunction cf = call_detail::call_user<void, false, false, destructor_wrapper<Fx>, 2>;
  569. int upvalues = 0;
  570. upvalues += stack::push(L, nullptr);
  571. upvalues += stack::push<user<destructor_wrapper<Fx>>>(L, c);
  572. return stack::push(L, c_closure(cf, upvalues));
  573. }
  574. };
  575. template <typename F, typename... Policies>
  576. struct unqualified_pusher<policy_wrapper<F, Policies...>> {
  577. using P = policy_wrapper<F, Policies...>;
  578. static int push(lua_State* L, const P& p) {
  579. lua_CFunction cf = call_detail::call_user<void, false, false, P, 2>;
  580. int upvalues = 0;
  581. upvalues += stack::push(L, nullptr);
  582. upvalues += stack::push<user<P>>(L, p);
  583. return stack::push(L, c_closure(cf, upvalues));
  584. }
  585. static int push(lua_State* L, P&& p) {
  586. lua_CFunction cf = call_detail::call_user<void, false, false, P, 2>;
  587. int upvalues = 0;
  588. upvalues += stack::push(L, nullptr);
  589. upvalues += stack::push<user<P>>(L, std::move(p));
  590. return stack::push(L, c_closure(cf, upvalues));
  591. }
  592. };
  593. template <typename T, typename F, typename... Policies>
  594. struct unqualified_pusher<detail::tagged<T, policy_wrapper<F, Policies...>>> {
  595. using P = policy_wrapper<F, Policies...>;
  596. using Tagged = detail::tagged<T, P>;
  597. static int push(lua_State* L, const Tagged& p) {
  598. lua_CFunction cf = call_detail::call_user<T, false, false, P, 2>;
  599. int upvalues = 0;
  600. upvalues += stack::push(L, nullptr);
  601. upvalues += stack::push<user<P>>(L, p.value());
  602. return stack::push(L, c_closure(cf, upvalues));
  603. }
  604. static int push(lua_State* L, Tagged&& p) {
  605. lua_CFunction cf = call_detail::call_user<T, false, false, P, 2>;
  606. int upvalues = 0;
  607. upvalues += stack::push(L, nullptr);
  608. upvalues += stack::push<user<P>>(L, std::move(p.value()));
  609. return stack::push(L, c_closure(cf, upvalues));
  610. }
  611. };
  612. template <typename T>
  613. struct unqualified_pusher<push_invoke_t<T>> {
  614. static int push(lua_State* L, push_invoke_t<T>&& pi) {
  615. if constexpr (std::is_invocable_v<std::add_rvalue_reference_t<T>, lua_State*>) {
  616. return stack::push(L, std::move(pi.value())(L));
  617. }
  618. else {
  619. return stack::push(L, std::move(pi.value())());
  620. }
  621. }
  622. static int push(lua_State* L, const push_invoke_t<T>& pi) {
  623. if constexpr (std::is_invocable_v<const T, lua_State*>) {
  624. return stack::push(L, pi.value()(L));
  625. }
  626. else {
  627. return stack::push(L, pi.value()());
  628. }
  629. }
  630. };
  631. namespace stack_detail {
  632. template <typename Function, typename Handler>
  633. bool check_function_pointer(lua_State* L, int index, Handler&& handler, record& tracking) noexcept {
  634. #if SOL_IS_ON(SOL_GET_FUNCTION_POINTER_UNSAFE)
  635. tracking.use(1);
  636. bool success = lua_iscfunction(L, index) == 1;
  637. if (success) {
  638. // there must be at LEAST 2 upvalues; otherwise, we didn't serialize it.
  639. const char* upvalue_name = lua_getupvalue(L, index, 2);
  640. lua_pop(L, 1);
  641. success = upvalue_name != nullptr;
  642. }
  643. if (!success) {
  644. // expected type, actual type
  645. handler(
  646. L, index, type::function, type_of(L, index), "type must be a Lua C Function gotten from a function pointer serialized by sol2");
  647. }
  648. return success;
  649. #else
  650. (void)L;
  651. (void)index;
  652. (void)handler;
  653. (void)tracking;
  654. return false;
  655. #endif
  656. }
  657. template <typename Function>
  658. Function* get_function_pointer(lua_State* L, int index, record& tracking) noexcept {
  659. #if SOL_IS_ON(SOL_GET_FUNCTION_POINTER_UNSAFE)
  660. tracking.use(1);
  661. auto udata = stack::stack_detail::get_as_upvalues_using_function<Function*>(L, index);
  662. Function* fx = udata.first;
  663. return fx;
  664. #else
  665. (void)L;
  666. (void)index;
  667. (void)tracking;
  668. static_assert(meta::meta_detail::always_true<Function>::value,
  669. #if SOL_IS_DEFAULT_OFF(SOL_GET_FUNCTION_POINTER_UNSAFE)
  670. "You are attempting to retrieve a function pointer type. "
  671. "This is inherently unsafe in sol2. In order to do this, you must turn on the "
  672. "SOL_GET_FUNCTION_POINTER_UNSAFE configuration macro, as detailed in the documentation. "
  673. "Please be careful!"
  674. #else
  675. "You are attempting to retrieve a function pointer type. "
  676. "You explicitly turned off the ability to do this by defining "
  677. "SOL_GET_FUNCTION_POINTER_UNSAFE or similar to be off. "
  678. "Please reconsider this!"
  679. #endif
  680. );
  681. return nullptr;
  682. #endif
  683. }
  684. } // namespace stack_detail
  685. } // namespace stack
  686. } // namespace sol
  687. #endif // SOL_FUNCTION_TYPES_HPP