1 // The MIT License (MIT) 2 3 // Copyright (c) 2013-2016 Rapptz, ThePhD and contributors 4 5 // Permission is hereby granted, free of charge, to any person obtaining a copy of 6 // this software and associated documentation files (the "Software"), to deal in 7 // the Software without restriction, including without limitation the rights to 8 // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 // the Software, and to permit persons to whom the Software is furnished to do so, 10 // subject to the following conditions: 11 12 // The above copyright notice and this permission notice shall be included in all 13 // copies or substantial portions of the Software. 14 15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 22 #ifndef SOL_FUNCTION_TYPES_HPP 23 #define SOL_FUNCTION_TYPES_HPP 24 25 #include "function_types_core.hpp" 26 #include "function_types_templated.hpp" 27 #include "function_types_stateless.hpp" 28 #include "function_types_stateful.hpp" 29 #include "function_types_overloaded.hpp" 30 #include "resolve.hpp" 31 #include "call.hpp" 32 33 namespace sol { 34 namespace stack { 35 template<typename... Sigs> 36 struct pusher<function_sig<Sigs...>> { 37 template <typename... Sig, typename Fx, typename... Args> select_convertiblesol::stack::pusher38 static void select_convertible(std::false_type, types<Sig...>, lua_State* L, Fx&& fx, Args&&... args) { 39 typedef std::remove_pointer_t<std::decay_t<Fx>> clean_fx; 40 typedef function_detail::functor_function<clean_fx> F; 41 set_fx<F>(L, std::forward<Fx>(fx), std::forward<Args>(args)...); 42 } 43 44 template <typename R, typename... A, typename Fx, typename... Args> select_convertiblesol::stack::pusher45 static void select_convertible(std::true_type, types<R(A...)>, lua_State* L, Fx&& fx, Args&&... args) { 46 using fx_ptr_t = R(*)(A...); 47 fx_ptr_t fxptr = detail::unwrap(std::forward<Fx>(fx)); 48 select_function(std::true_type(), L, fxptr, std::forward<Args>(args)...); 49 } 50 51 template <typename R, typename... A, typename Fx, typename... Args> select_convertiblesol::stack::pusher52 static void select_convertible(types<R(A...)> t, lua_State* L, Fx&& fx, Args&&... args) { 53 typedef std::decay_t<meta::unwrap_unqualified_t<Fx>> raw_fx_t; 54 typedef R(*fx_ptr_t)(A...); 55 typedef std::is_convertible<raw_fx_t, fx_ptr_t> is_convertible; 56 select_convertible(is_convertible(), t, L, std::forward<Fx>(fx), std::forward<Args>(args)...); 57 } 58 59 template <typename Fx, typename... Args> select_convertiblesol::stack::pusher60 static void select_convertible(types<>, lua_State* L, Fx&& fx, Args&&... args) { 61 typedef meta::function_signature_t<meta::unwrap_unqualified_t<Fx>> Sig; 62 select_convertible(types<Sig>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...); 63 } 64 65 template <typename Fx, typename T, typename... Args> select_reference_member_variablesol::stack::pusher66 static void select_reference_member_variable(std::false_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { 67 typedef std::remove_pointer_t<std::decay_t<Fx>> clean_fx; 68 typedef function_detail::member_variable<meta::unwrap_unqualified_t<T>, clean_fx> F; 69 set_fx<F>(L, std::forward<Fx>(fx), std::forward<T>(obj), std::forward<Args>(args)...); 70 } 71 72 template <typename Fx, typename T, typename... Args> select_reference_member_variablesol::stack::pusher73 static void select_reference_member_variable(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { 74 typedef std::decay_t<Fx> dFx; 75 dFx memfxptr(std::forward<Fx>(fx)); 76 auto userptr = detail::ptr(std::forward<T>(obj), std::forward<Args>(args)...); 77 lua_CFunction freefunc = &function_detail::upvalue_member_variable<std::decay_t<decltype(*userptr)>, meta::unqualified_t<Fx>>::call; 78 79 int upvalues = stack::stack_detail::push_as_upvalues(L, memfxptr); 80 upvalues += stack::push(L, lightuserdata_value(static_cast<void*>(userptr))); 81 stack::push(L, c_closure(freefunc, upvalues)); 82 } 83 84 template <typename Fx, typename... Args> select_member_variablesol::stack::pusher85 static void select_member_variable(std::false_type, lua_State* L, Fx&& fx, Args&&... args) { 86 select_convertible(types<Sigs...>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...); 87 } 88 89 template <typename Fx, typename T, typename... Args> select_member_variablesol::stack::pusher90 static void select_member_variable(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { 91 typedef meta::boolean<meta::is_specialization_of<std::reference_wrapper, meta::unqualified_t<T>>::value || std::is_pointer<T>::value> is_reference; 92 select_reference_member_variable(is_reference(), L, std::forward<Fx>(fx), std::forward<T>(obj), std::forward<Args>(args)...); 93 } 94 95 template <typename Fx> select_member_variablesol::stack::pusher96 static void select_member_variable(std::true_type, lua_State* L, Fx&& fx) { 97 typedef typename meta::bind_traits<meta::unqualified_t<Fx>>::object_type C; 98 lua_CFunction freefunc = &function_detail::upvalue_this_member_variable<C, Fx>::call; 99 int upvalues = stack::stack_detail::push_as_upvalues(L, fx); 100 stack::push(L, c_closure(freefunc, upvalues)); 101 } 102 103 template <typename Fx, typename T, typename... Args> select_reference_member_functionsol::stack::pusher104 static void select_reference_member_function(std::false_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { 105 typedef std::decay_t<Fx> clean_fx; 106 typedef function_detail::member_function<meta::unwrap_unqualified_t<T>, clean_fx> F; 107 set_fx<F>(L, std::forward<Fx>(fx), std::forward<T>(obj), std::forward<Args>(args)...); 108 } 109 110 template <typename Fx, typename T, typename... Args> select_reference_member_functionsol::stack::pusher111 static void select_reference_member_function(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { 112 typedef std::decay_t<Fx> dFx; 113 dFx memfxptr(std::forward<Fx>(fx)); 114 auto userptr = detail::ptr(std::forward<T>(obj), std::forward<Args>(args)...); 115 lua_CFunction freefunc = &function_detail::upvalue_member_function<std::decay_t<decltype(*userptr)>, meta::unqualified_t<Fx>>::call; 116 117 int upvalues = stack::stack_detail::push_as_upvalues(L, memfxptr); 118 upvalues += stack::push(L, lightuserdata_value(static_cast<void*>(userptr))); 119 stack::push(L, c_closure(freefunc, upvalues)); 120 } 121 122 template <typename Fx, typename... Args> select_member_functionsol::stack::pusher123 static void select_member_function(std::false_type, lua_State* L, Fx&& fx, Args&&... args) { 124 select_member_variable(std::is_member_object_pointer<meta::unqualified_t<Fx>>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...); 125 } 126 127 template <typename Fx, typename T, typename... Args> select_member_functionsol::stack::pusher128 static void select_member_function(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { 129 typedef meta::boolean<meta::is_specialization_of<std::reference_wrapper, meta::unqualified_t<T>>::value || std::is_pointer<T>::value> is_reference; 130 select_reference_member_function(is_reference(), L, std::forward<Fx>(fx), std::forward<T>(obj), std::forward<Args>(args)...); 131 } 132 133 template <typename Fx> select_member_functionsol::stack::pusher134 static void select_member_function(std::true_type, lua_State* L, Fx&& fx) { 135 typedef typename meta::bind_traits<meta::unqualified_t<Fx>>::object_type C; 136 lua_CFunction freefunc = &function_detail::upvalue_this_member_function<C, Fx>::call; 137 int upvalues = stack::stack_detail::push_as_upvalues(L, fx); 138 stack::push(L, c_closure(freefunc, upvalues)); 139 } 140 141 template <typename Fx, typename... Args> select_functionsol::stack::pusher142 static void select_function(std::false_type, lua_State* L, Fx&& fx, Args&&... args) { 143 select_member_function(std::is_member_function_pointer<meta::unqualified_t<Fx>>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...); 144 } 145 146 template <typename Fx, typename... Args> select_functionsol::stack::pusher147 static void select_function(std::true_type, lua_State* L, Fx&& fx, Args&&... args) { 148 std::decay_t<Fx> target(std::forward<Fx>(fx), std::forward<Args>(args)...); 149 lua_CFunction freefunc = &function_detail::upvalue_free_function<Fx>::call; 150 151 int upvalues = stack::stack_detail::push_as_upvalues(L, target); 152 stack::push(L, c_closure(freefunc, upvalues)); 153 } 154 select_functionsol::stack::pusher155 static void select_function(std::true_type, lua_State* L, lua_CFunction f) { 156 stack::push(L, f); 157 } 158 159 template <typename Fx, typename... Args> selectsol::stack::pusher160 static void select(lua_State* L, Fx&& fx, Args&&... args) { 161 select_function(std::is_function<meta::unqualified_t<Fx>>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...); 162 } 163 164 template <typename Fx, typename... Args> set_fxsol::stack::pusher165 static void set_fx(lua_State* L, Args&&... args) { 166 lua_CFunction freefunc = function_detail::call<meta::unqualified_t<Fx>>; 167 168 stack::push_specific<user<Fx>>(L, std::forward<Args>(args)...); 169 stack::push(L, c_closure(freefunc, 1)); 170 } 171 172 template<typename... Args> pushsol::stack::pusher173 static int push(lua_State* L, Args&&... args) { 174 // Set will always place one thing (function) on the stack 175 select(L, std::forward<Args>(args)...); 176 return 1; 177 } 178 }; 179 180 template<typename T, typename... Args> 181 struct pusher<function_arguments<T, Args...>> { 182 template <std::size_t... I, typename FP> push_funcsol::stack::pusher183 static int push_func(std::index_sequence<I...>, lua_State* L, FP&& fp) { 184 return stack::push_specific<T>(L, detail::forward_get<I>(fp.arguments)...); 185 } 186 pushsol::stack::pusher187 static int push(lua_State* L, const function_arguments<T, Args...>& fp) { 188 return push_func(std::make_index_sequence<sizeof...(Args)>(), L, fp); 189 } 190 pushsol::stack::pusher191 static int push(lua_State* L, function_arguments<T, Args...>&& fp) { 192 return push_func(std::make_index_sequence<sizeof...(Args)>(), L, std::move(fp)); 193 } 194 }; 195 196 template<typename Signature> 197 struct pusher<std::function<Signature>> { pushsol::stack::pusher198 static int push(lua_State* L, std::function<Signature> fx) { 199 return pusher<function_sig<Signature>>{}.push(L, std::move(fx)); 200 } 201 }; 202 203 template<typename Signature> 204 struct pusher<Signature, std::enable_if_t<std::is_member_pointer<Signature>::value>> { 205 template <typename F> pushsol::stack::pusher206 static int push(lua_State* L, F&& f) { 207 return pusher<function_sig<>>{}.push(L, std::forward<F>(f)); 208 } 209 }; 210 211 template<typename Signature> 212 struct pusher<Signature, std::enable_if_t<meta::all<std::is_function<Signature>, meta::neg<std::is_same<Signature, lua_CFunction>>, meta::neg<std::is_same<Signature, std::remove_pointer_t<lua_CFunction>>>>::value>> { 213 template <typename F> pushsol::stack::pusher214 static int push(lua_State* L, F&& f) { 215 return pusher<function_sig<>>{}.push(L, std::forward<F>(f)); 216 } 217 }; 218 219 template<typename... Functions> 220 struct pusher<overload_set<Functions...>> { pushsol::stack::pusher221 static int push(lua_State* L, overload_set<Functions...>&& set) { 222 typedef function_detail::overloaded_function<Functions...> F; 223 pusher<function_sig<>>{}.set_fx<F>(L, std::move(set.functions)); 224 return 1; 225 } 226 pushsol::stack::pusher227 static int push(lua_State* L, const overload_set<Functions...>& set) { 228 typedef function_detail::overloaded_function<Functions...> F; 229 pusher<function_sig<>>{}.set_fx<F>(L, set.functions); 230 return 1; 231 } 232 }; 233 234 template <typename T> 235 struct pusher<protect_t<T>> { pushsol::stack::pusher236 static int push(lua_State* L, protect_t<T>&& pw) { 237 lua_CFunction cf = call_detail::call_user<void, false, false, protect_t<T>>; 238 int closures = stack::push_specific<user<protect_t<T>>>(L, std::move(pw.value)); 239 return stack::push(L, c_closure(cf, closures)); 240 } 241 pushsol::stack::pusher242 static int push(lua_State* L, const protect_t<T>& pw) { 243 lua_CFunction cf = call_detail::call_user<void, false, false, protect_t<T>>; 244 int closures = stack::push_specific<user<protect_t<T>>>(L, pw.value); 245 return stack::push(L, c_closure(cf, closures)); 246 } 247 }; 248 249 template <typename F, typename G> 250 struct pusher<property_wrapper<F, G>, std::enable_if_t<!std::is_void<F>::value && !std::is_void<G>::value>> { pushsol::stack::pusher251 static int push(lua_State* L, property_wrapper<F, G>&& pw) { 252 return stack::push(L, sol::overload(std::move(pw.read), std::move(pw.write))); 253 } pushsol::stack::pusher254 static int push(lua_State* L, const property_wrapper<F, G>& pw) { 255 return stack::push(L, sol::overload(pw.read, pw.write)); 256 } 257 }; 258 259 template <typename F> 260 struct pusher<property_wrapper<F, void>> { pushsol::stack::pusher261 static int push(lua_State* L, property_wrapper<F, void>&& pw) { 262 return stack::push(L, std::move(pw.read)); 263 } pushsol::stack::pusher264 static int push(lua_State* L, const property_wrapper<F, void>& pw) { 265 return stack::push(L, pw.read); 266 } 267 }; 268 269 template <typename F> 270 struct pusher<property_wrapper<void, F>> { pushsol::stack::pusher271 static int push(lua_State* L, property_wrapper<void, F>&& pw) { 272 return stack::push(L, std::move(pw.write)); 273 } pushsol::stack::pusher274 static int push(lua_State* L, const property_wrapper<void, F>& pw) { 275 return stack::push(L, pw.write); 276 } 277 }; 278 279 template <typename T> 280 struct pusher<var_wrapper<T>> { pushsol::stack::pusher281 static int push(lua_State* L, var_wrapper<T>&& vw) { 282 return stack::push(L, std::move(vw.value)); 283 } pushsol::stack::pusher284 static int push(lua_State* L, const var_wrapper<T>& vw) { 285 return stack::push(L, vw.value); 286 } 287 }; 288 289 template <typename... Functions> 290 struct pusher<factory_wrapper<Functions...>> { pushsol::stack::pusher291 static int push(lua_State* L, const factory_wrapper<Functions...>& fw) { 292 typedef function_detail::overloaded_function<Functions...> F; 293 pusher<function_sig<>>{}.set_fx<F>(L, fw.functions); 294 return 1; 295 } 296 pushsol::stack::pusher297 static int push(lua_State* L, factory_wrapper<Functions...>&& fw) { 298 typedef function_detail::overloaded_function<Functions...> F; 299 pusher<function_sig<>>{}.set_fx<F>(L, std::move(fw.functions)); 300 return 1; 301 } 302 }; 303 304 template <typename T, typename... Lists> 305 struct pusher<detail::tagged<T, constructor_list<Lists...>>> { pushsol::stack::pusher306 static int push(lua_State* L, detail::tagged<T, constructor_list<Lists...>>) { 307 lua_CFunction cf = call_detail::construct<T, Lists...>; 308 return stack::push(L, cf); 309 } 310 }; 311 312 template <typename T, typename... Fxs> 313 struct pusher<detail::tagged<T, constructor_wrapper<Fxs...>>> { 314 template <typename C> pushsol::stack::pusher315 static int push(lua_State* L, C&& c) { 316 lua_CFunction cf = call_detail::call_user<T, false, false, constructor_wrapper<Fxs...>>; 317 int closures = stack::push_specific<user<constructor_wrapper<Fxs...>>>(L, std::forward<C>(c)); 318 return stack::push(L, c_closure(cf, closures)); 319 } 320 }; 321 322 template <typename T> 323 struct pusher<detail::tagged<T, destructor_wrapper<void>>> { pushsol::stack::pusher324 static int push(lua_State* L, destructor_wrapper<void>) { 325 lua_CFunction cf = detail::usertype_alloc_destroy<T>; 326 return stack::push(L, cf); 327 } 328 }; 329 330 template <typename T, typename Fx> 331 struct pusher<detail::tagged<T, destructor_wrapper<Fx>>> { pushsol::stack::pusher332 static int push(lua_State* L, destructor_wrapper<Fx> c) { 333 lua_CFunction cf = call_detail::call_user<T, false, false, destructor_wrapper<Fx>>; 334 int closures = stack::push_specific<user<T>>(L, std::move(c)); 335 return stack::push(L, c_closure(cf, closures)); 336 } 337 }; 338 339 } // stack 340 } // sol 341 342 #endif // SOL_FUNCTION_TYPES_HPP 343