1 // Copyright (c) 2003 Daniel Wallin and Arvid Norberg 2 3 // Permission is hereby granted, free of charge, to any person obtaining a 4 // copy of this software and associated documentation files (the "Software"), 5 // to deal in the Software without restriction, including without limitation 6 // the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 // and/or sell copies of the Software, and to permit persons to whom the 8 // Software is furnished to do so, subject to the following conditions: 9 10 // The above copyright notice and this permission notice shall be included 11 // in all copies or substantial portions of the Software. 12 13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 14 // ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 15 // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 16 // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 17 // SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR 18 // ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 19 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE 21 // OR OTHER DEALINGS IN THE SOFTWARE. 22 23 #if !BOOST_PP_IS_ITERATING 24 25 #ifndef LUABIND_WRAPPER_BASE_HPP_INCLUDED 26 #define LUABIND_WRAPPER_BASE_HPP_INCLUDED 27 28 #include <luabind/config.hpp> 29 #include <luabind/weak_ref.hpp> 30 #include <luabind/detail/ref.hpp> 31 #include <luabind/detail/call_member.hpp> 32 33 #include <boost/preprocessor/repetition/enum_trailing_params.hpp> 34 #include <boost/preprocessor/repetition/enum_trailing_binary_params.hpp> 35 36 #include <stdexcept> 37 38 namespace luabind 39 { 40 namespace detail 41 { 42 struct wrap_access; 43 44 // implements the selection between dynamic dispatch 45 // or default implementation calls from within a virtual 46 // function wrapper. The input is the self reference on 47 // the top of the stack. Output is the function to call 48 // on the top of the stack (the input self reference will 49 // be popped) 50 LUABIND_API void do_call_member_selection(lua_State* L, char const* name); 51 } 52 53 struct wrapped_self_t: weak_ref 54 { 55 detail::lua_reference m_strong_ref; 56 }; 57 58 struct wrap_base 59 { 60 friend struct detail::wrap_access; wrap_baseluabind::wrap_base61 wrap_base() {} 62 63 #define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, <luabind/wrapper_base.hpp>, 1)) 64 #include BOOST_PP_ITERATE() 65 66 private: 67 wrapped_self_t m_self; 68 }; 69 70 #define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, <luabind/wrapper_base.hpp>, 2)) 71 #include BOOST_PP_ITERATE() 72 73 namespace detail 74 { 75 struct wrap_access 76 { refluabind::detail::wrap_access77 static wrapped_self_t const& ref(wrap_base const& b) 78 { 79 return b.m_self; 80 } 81 refluabind::detail::wrap_access82 static wrapped_self_t& ref(wrap_base& b) 83 { 84 return b.m_self; 85 } 86 }; 87 } 88 } 89 90 #endif // LUABIND_WRAPPER_BASE_HPP_INCLUDED 91 92 #else 93 #if BOOST_PP_ITERATION_FLAGS() == 1 94 95 #define LUABIND_TUPLE_PARAMS(z, n, data) const A##n * 96 #define LUABIND_OPERATOR_PARAMS(z, n, data) const A##n & a##n 97 98 template<class R BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A)> 99 typename boost::mpl::if_<boost::is_void<R> 100 , luabind::detail::proxy_member_void_caller<boost::tuples::tuple<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS, _)> > 101 , luabind::detail::proxy_member_caller<R, boost::tuples::tuple<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS, _)> > >::type call(char const * name BOOST_PP_COMMA_IF (BOOST_PP_ITERATION ())BOOST_PP_ENUM (BOOST_PP_ITERATION (),LUABIND_OPERATOR_PARAMS,_),detail::type_<R> * =0) const102 call(char const* name BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_OPERATOR_PARAMS, _), detail::type_<R>* = 0) const 103 { 104 typedef boost::tuples::tuple<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS, _)> tuple_t; 105 #if BOOST_PP_ITERATION() == 0 106 tuple_t args; 107 #else 108 tuple_t args(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), &a)); 109 #endif 110 111 typedef typename boost::mpl::if_<boost::is_void<R> 112 , luabind::detail::proxy_member_void_caller<boost::tuples::tuple<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS, _)> > 113 , luabind::detail::proxy_member_caller<R, boost::tuples::tuple<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS, _)> > >::type proxy_type; 114 115 // this will be cleaned up by the proxy object 116 // once the call has been made 117 118 // TODO: what happens if this virtual function is 119 // dispatched from a lua thread where the state 120 // pointer is different? 121 122 // get the function 123 lua_State* L = m_self.state(); 124 m_self.get(L); 125 assert(!lua_isnil(L, -1)); 126 detail::do_call_member_selection(L, name); 127 128 if (lua_isnil(L, -1)) 129 { 130 lua_pop(L, 1); 131 throw std::runtime_error("Attempt to call nonexistent function"); 132 } 133 134 // push the self reference as the first parameter 135 m_self.get(L); 136 137 // now the function and self objects 138 // are on the stack. These will both 139 // be popped by pcall 140 return proxy_type(L, args); 141 } 142 143 #undef LUABIND_CALL_MEMBER_NAME 144 #undef LUABIND_OPERATOR_PARAMS 145 #undef LUABIND_TUPLE_PARAMS 146 147 #else // free call_member forwardarding functions 148 149 #define N BOOST_PP_ITERATION() 150 151 #define LUABIND_TUPLE_PARAMS(z, n, data) const A##n * 152 #define LUABIND_OPERATOR_PARAMS(z, n, data) const A##n & a##n 153 154 template< 155 class R 156 BOOST_PP_ENUM_TRAILING_PARAMS(N, class A) 157 > 158 typename boost::mpl::if_< 159 boost::is_void<R> 160 , detail::proxy_member_void_caller< 161 boost::tuples::tuple< 162 BOOST_PP_ENUM(N, LUABIND_TUPLE_PARAMS, _) 163 > 164 > 165 , detail::proxy_member_caller< 166 R 167 , boost::tuples::tuple< 168 BOOST_PP_ENUM(N, LUABIND_TUPLE_PARAMS, _) 169 > 170 > 171 >::type call_member(wrap_base const * self,char const * fn BOOST_PP_ENUM_TRAILING_BINARY_PARAMS (N,A,& a),detail::type_<R> * =0)172 call_member( 173 wrap_base const* self 174 , char const* fn 175 BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(N, A, &a) 176 , detail::type_<R>* = 0 177 ) 178 { 179 return self->call( 180 fn 181 BOOST_PP_ENUM_TRAILING_PARAMS(N, a) 182 , (detail::type_<R>*)0 183 ); 184 } 185 186 #undef LUABIND_OPERATOR_PARAMS 187 #undef LUABIND_TUPLE_PARAMS 188 189 #undef N 190 191 #endif 192 #endif 193