1 // Copyright (c) 2003 Daniel Wallin and Arvid Norberg
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:
10 // The above copyright notice and this permission notice shall be included
11 // in all copies or substantial portions of the Software.
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.
23 #if !BOOST_PP_IS_ITERATING
25 #ifndef LUABIND_WRAPPER_BASE_HPP_INCLUDED
26 #define LUABIND_WRAPPER_BASE_HPP_INCLUDED
28 #include <luabind/config.hpp>
29 #include <luabind/weak_ref.hpp>
30 #include <luabind/detail/ref.hpp>
31 #include <luabind/detail/call_member.hpp>
33 #include <boost/preprocessor/repetition/enum_trailing_params.hpp>
34 #include <boost/preprocessor/repetition/enum_trailing_binary_params.hpp>
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
50 LUABIND_API
void do_call_member_selection(lua_State
* L
, char const* name
);
53 struct wrapped_self_t
: weak_ref
55 detail::lua_reference m_strong_ref
;
60 friend struct detail::wrap_access
;
63 #define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, <luabind/wrapper_base.hpp>, 1))
64 #include BOOST_PP_ITERATE()
67 wrapped_self_t m_self
;
70 #define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, <luabind/wrapper_base.hpp>, 2))
71 #include BOOST_PP_ITERATE()
77 static wrapped_self_t
const& ref(wrap_base
const& b
)
82 static wrapped_self_t
& ref(wrap_base
& b
)
90 #endif // LUABIND_WRAPPER_BASE_HPP_INCLUDED
92 #elif BOOST_PP_ITERATION_FLAGS() == 1
94 #define LUABIND_TUPLE_PARAMS(z, n, data) const A##n *
95 #define LUABIND_OPERATOR_PARAMS(z, n, data) const A##n & a##n
97 template<class R
BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A
)>
98 typename
boost::mpl::if_
<boost::is_void
<R
>
99 , luabind::detail::proxy_member_void_caller
<boost::tuples::tuple
<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS
, _
)> >
100 , luabind::detail::proxy_member_caller
<R
, boost::tuples::tuple
<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS
, _
)> > >::type
101 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 typedef boost::tuples::tuple
<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS
, _
)> tuple_t
;
104 #if BOOST_PP_ITERATION() == 0
107 tuple_t
args(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), &a
));
110 typedef typename
boost::mpl::if_
<boost::is_void
<R
>
111 , luabind::detail::proxy_member_void_caller
<boost::tuples::tuple
<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS
, _
)> >
112 , luabind::detail::proxy_member_caller
<R
, boost::tuples::tuple
<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS
, _
)> > >::type proxy_type
;
114 // this will be cleaned up by the proxy object
115 // once the call has been made
117 // TODO: what happens if this virtual function is
118 // dispatched from a lua thread where the state
119 // pointer is different?
122 lua_State
* L
= m_self
.state();
124 assert(!lua_isnil(L
, -1));
125 detail::do_call_member_selection(L
, name
);
127 if (lua_isnil(L
, -1))
130 throw std::runtime_error("Attempt to call nonexistent function");
133 // push the self reference as the first parameter
136 // now the function and self objects
137 // are on the stack. These will both
138 // be popped by pcall
139 return proxy_type(L
, args
);
142 #undef LUABIND_CALL_MEMBER_NAME
143 #undef LUABIND_OPERATOR_PARAMS
144 #undef LUABIND_TUPLE_PARAMS
146 #else // free call_member forwardarding functions
148 #define N BOOST_PP_ITERATION()
150 #define LUABIND_TUPLE_PARAMS(z, n, data) const A##n *
151 #define LUABIND_OPERATOR_PARAMS(z, n, data) const A##n & a##n
155 BOOST_PP_ENUM_TRAILING_PARAMS(N
, class A
)
157 typename
boost::mpl::if_
<
159 , detail::proxy_member_void_caller
<
160 boost::tuples::tuple
<
161 BOOST_PP_ENUM(N
, LUABIND_TUPLE_PARAMS
, _
)
164 , detail::proxy_member_caller
<
166 , boost::tuples::tuple
<
167 BOOST_PP_ENUM(N
, LUABIND_TUPLE_PARAMS
, _
)
172 wrap_base
const* self
174 BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(N
, A
, &a
)
175 , detail::type_
<R
>* = 0
180 BOOST_PP_ENUM_TRAILING_PARAMS(N
, a
)
181 , (detail::type_
<R
>*)0
185 #undef LUABIND_OPERATOR_PARAMS
186 #undef LUABIND_TUPLE_PARAMS