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.
24 #if !BOOST_PP_IS_ITERATING
26 #ifndef LUABIND_CALL_MEMBER_HPP_INCLUDED
27 #define LUABIND_CALL_MEMBER_HPP_INCLUDED
29 #include <luabind/config.hpp>
30 #include <luabind/detail/convert_to_lua.hpp>
31 #include <luabind/detail/pcall.hpp>
32 #include <luabind/error.hpp>
33 #include <luabind/detail/stack_utils.hpp>
34 #include <luabind/object.hpp> // TODO: REMOVE DEPENDENCY
36 #include <boost/tuple/tuple.hpp>
38 #include <boost/preprocessor/control/if.hpp>
39 #include <boost/preprocessor/facilities/expand.hpp>
41 #include <boost/mpl/apply_wrap.hpp>
48 namespace mpl
= boost::mpl
;
50 // if the proxy_member_caller returns non-void
51 template<class Ret
, class Tuple
>
52 class proxy_member_caller
54 // friend class luabind::object;
57 proxy_member_caller(lua_State
* L_
, const Tuple args
)
64 proxy_member_caller(const proxy_member_caller
& rhs
)
67 , m_called(rhs
.m_called
)
72 ~proxy_member_caller()
78 // don't count the function and self-reference
79 // since those will be popped by pcall
80 int top
= lua_gettop(L
) - 2;
82 // pcall will pop the function and self reference
83 // and all the parameters
85 push_args_from_tuple
<1>::apply(L
, m_args
);
86 if (pcall(L
, boost::tuples::length
<Tuple
>::value
+ 1, 0))
88 assert(lua_gettop(L
) == top
+ 1);
89 #ifndef LUABIND_NO_EXCEPTIONS
90 throw luabind::error(L
);
92 error_callback_fun e
= get_error_callback();
95 assert(0 && "the lua function threw an error and exceptions are disabled."
96 "If you want to handle this error use luabind::set_error_callback()");
100 // pops the return values from the function
101 stack_pop
pop(L
, lua_gettop(L
) - top
);
106 typename
mpl::apply_wrap2
<default_policy
,Ret
,lua_to_cpp
>::type converter
;
110 // don't count the function and self-reference
111 // since those will be popped by pcall
112 int top
= lua_gettop(L
) - 2;
114 // pcall will pop the function and self reference
115 // and all the parameters
116 push_args_from_tuple
<1>::apply(L
, m_args
);
117 if (pcall(L
, boost::tuples::length
<Tuple
>::value
+ 1, 1))
119 assert(lua_gettop(L
) == top
+ 1);
120 #ifndef LUABIND_NO_EXCEPTIONS
121 throw luabind::error(L
);
123 error_callback_fun e
= get_error_callback();
126 assert(0 && "the lua function threw an error and exceptions are disabled."
127 "If you want to handle this error use luabind::set_error_callback()");
132 // pops the return values from the function
133 stack_pop
pop(L
, lua_gettop(L
) - top
);
135 #ifndef LUABIND_NO_ERROR_CHECKING
137 if (converter
.match(L
, LUABIND_DECORATE_TYPE(Ret
), -1) < 0)
139 assert(lua_gettop(L
) == top
+ 1);
140 #ifndef LUABIND_NO_EXCEPTIONS
141 throw cast_failed(L
, LUABIND_TYPEID(Ret
));
143 cast_failed_callback_fun e
= get_cast_failed_callback();
144 if (e
) e(L
, LUABIND_TYPEID(Ret
));
146 assert(0 && "the lua function's return value could not be converted."
147 "If you want to handle this error use luabind::set_error_callback()");
152 return converter
.apply(L
, LUABIND_DECORATE_TYPE(Ret
), -1);
155 template<class Policies
>
156 Ret
operator[](const Policies
& p
)
158 typedef typename find_conversion_policy
<0, Policies
>::type converter_policy
;
159 typename
mpl::apply_wrap2
<converter_policy
,Ret
,lua_to_cpp
>::type converter
;
163 // don't count the function and self-reference
164 // since those will be popped by pcall
165 int top
= lua_gettop(L
) - 2;
167 // pcall will pop the function and self reference
168 // and all the parameters
170 detail::push_args_from_tuple
<1>::apply(L
, m_args
, p
);
171 if (pcall(L
, boost::tuples::length
<Tuple
>::value
+ 1, 1))
173 assert(lua_gettop(L
) == top
+ 1);
174 #ifndef LUABIND_NO_EXCEPTIONS
177 error_callback_fun e
= get_error_callback();
180 assert(0 && "the lua function threw an error and exceptions are disabled."
181 "If you want to handle this error use luabind::set_error_callback()");
186 // pops the return values from the function
187 stack_pop
pop(L
, lua_gettop(L
) - top
);
189 #ifndef LUABIND_NO_ERROR_CHECKING
191 if (converter
.match(L
, LUABIND_DECORATE_TYPE(Ret
), -1) < 0)
193 assert(lua_gettop(L
) == top
+ 1);
194 #ifndef LUABIND_NO_EXCEPTIONS
195 throw cast_failed(L
, LUABIND_TYPEID(Ret
));
197 cast_failed_callback_fun e
= get_cast_failed_callback();
198 if (e
) e(L
, LUABIND_TYPEID(Ret
));
200 assert(0 && "the lua function's return value could not be converted."
201 "If you want to handle this error use luabind::set_error_callback()");
206 return converter
.apply(L
, LUABIND_DECORATE_TYPE(Ret
), -1);
213 mutable bool m_called
;
217 // if the proxy_member_caller returns void
218 template<class Tuple
>
219 class proxy_member_void_caller
221 friend class luabind::object
;
224 proxy_member_void_caller(lua_State
* L_
, const Tuple args
)
231 proxy_member_void_caller(const proxy_member_void_caller
& rhs
)
234 , m_called(rhs
.m_called
)
239 ~proxy_member_void_caller()
241 if (m_called
) return;
245 // don't count the function and self-reference
246 // since those will be popped by pcall
247 int top
= lua_gettop(L
) - 2;
249 // pcall will pop the function and self reference
250 // and all the parameters
252 push_args_from_tuple
<1>::apply(L
, m_args
);
253 if (pcall(L
, boost::tuples::length
<Tuple
>::value
+ 1, 0))
255 assert(lua_gettop(L
) == top
+ 1);
256 #ifndef LUABIND_NO_EXCEPTIONS
257 throw luabind::error(L
);
259 error_callback_fun e
= get_error_callback();
262 assert(0 && "the lua function threw an error and exceptions are disabled."
263 "If you want to handle this error use luabind::set_error_callback()");
267 // pops the return values from the function
268 stack_pop
pop(L
, lua_gettop(L
) - top
);
271 template<class Policies
>
272 void operator[](const Policies
& p
)
276 // don't count the function and self-reference
277 // since those will be popped by pcall
278 int top
= lua_gettop(L
) - 2;
280 // pcall will pop the function and self reference
281 // and all the parameters
283 detail::push_args_from_tuple
<1>::apply(L
, m_args
, p
);
284 if (pcall(L
, boost::tuples::length
<Tuple
>::value
+ 1, 0))
286 assert(lua_gettop(L
) == top
+ 1);
287 #ifndef LUABIND_NO_EXCEPTIONS
290 error_callback_fun e
= get_error_callback();
293 assert(0 && "the lua function threw an error and exceptions are disabled."
294 "If you want to handle this error use luabind::set_error_callback()");
298 // pops the return values from the function
299 stack_pop
pop(L
, lua_gettop(L
) - top
);
305 mutable bool m_called
;
311 #define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, <luabind/detail/call_member.hpp>, 1))
312 #include BOOST_PP_ITERATE()
316 #endif // LUABIND_CALL_MEMBER_HPP_INCLUDED
318 #elif BOOST_PP_ITERATION_FLAGS() == 1
320 #define LUABIND_TUPLE_PARAMS(z, n, data) const A##n *
321 #define LUABIND_OPERATOR_PARAMS(z, n, data) const A##n & a##n
323 template<class R
BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A
)>
324 typename
boost::mpl::if_
<boost::is_void
<R
>
325 , luabind::detail::proxy_member_void_caller
<boost::tuples::tuple
<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS
, _
)> >
326 , luabind::detail::proxy_member_caller
<R
, boost::tuples::tuple
<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS
, _
)> > >::type
327 call_member(object
const& obj
, const char* name
BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_OPERATOR_PARAMS
, _
))
329 typedef boost::tuples::tuple
<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS
, _
)> tuple_t
;
330 #if BOOST_PP_ITERATION() == 0
333 tuple_t
args(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), &a
));
336 typedef typename
boost::mpl::if_
<boost::is_void
<R
>
337 , luabind::detail::proxy_member_void_caller
<boost::tuples::tuple
<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS
, _
)> >
338 , luabind::detail::proxy_member_caller
<R
, boost::tuples::tuple
<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS
, _
)> > >::type proxy_type
;
340 // this will be cleaned up by the proxy object
341 // once the call has been made
344 obj
.push(obj
.interpreter());
345 lua_pushstring(obj
.interpreter(), name
);
346 lua_gettable(obj
.interpreter(), -2);
347 // duplicate the self-object
348 lua_pushvalue(obj
.interpreter(), -2);
349 // remove the bottom self-object
350 lua_remove(obj
.interpreter(), -3);
352 // now the function and self objects
353 // are on the stack. These will both
354 // be popped by pcall
355 return proxy_type(obj
.interpreter(), args
);
358 #undef LUABIND_OPERATOR_PARAMS
359 #undef LUABIND_TUPLE_PARAMS