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_FUNCTION_HPP_INCLUDED
27 #define LUABIND_CALL_FUNCTION_HPP_INCLUDED
29 #include <luabind/config.hpp>
31 #include <boost/mpl/if.hpp>
32 #include <boost/tuple/tuple.hpp>
33 #include <boost/mpl/or.hpp>
35 # include <boost/preprocessor/repeat.hpp>
36 # include <boost/preprocessor/iteration/iterate.hpp>
37 # include <boost/preprocessor/repetition/enum.hpp>
38 # include <boost/preprocessor/repetition/enum_params.hpp>
39 # include <boost/preprocessor/repetition/enum_binary_params.hpp>
40 # include <boost/preprocessor/punctuation/comma_if.hpp>
43 #include <luabind/error.hpp>
44 #include <luabind/detail/convert_to_lua.hpp>
45 #include <luabind/detail/pcall.hpp>
52 // if the proxy_function_caller returns non-void
53 template<class Ret
, class Tuple
>
54 class proxy_function_caller
56 // friend class luabind::object;
59 typedef int(*function_t
)(lua_State
*, int, int);
61 proxy_function_caller(
74 proxy_function_caller(const proxy_function_caller
& rhs
)
75 : m_state(rhs
.m_state
)
76 , m_params(rhs
.m_params
)
79 , m_called(rhs
.m_called
)
84 ~proxy_function_caller()
89 lua_State
* L
= m_state
;
91 int top
= lua_gettop(L
);
93 push_args_from_tuple
<1>::apply(L
, m_args
);
95 if (m_fun(L
, std::tuple_size
<Tuple
>::value
, 0))
97 if (m_fun(L
, boost::tuples::length
<Tuple
>::value
, 0))
100 assert(lua_gettop(L
) == top
- m_params
+ 1);
101 #ifndef LUABIND_NO_EXCEPTIONS
102 throw luabind::error(L
);
104 error_callback_fun e
= get_error_callback();
107 assert(0 && "the lua function threw an error and exceptions are disabled."
108 " If you want to handle the error you can use luabind::set_error_callback()");
114 // pops the return values from the function call
115 stack_pop
pop(L
, lua_gettop(L
) - top
+ m_params
);
120 typename
mpl::apply_wrap2
<default_policy
,Ret
,lua_to_cpp
>::type converter
;
123 lua_State
* L
= m_state
;
125 int top
= lua_gettop(L
);
127 push_args_from_tuple
<1>::apply(L
, m_args
);
128 # ifdef LUABIND_CPP0x
129 if (m_fun(L
, std::tuple_size
<Tuple
>::value
, 1))
131 if (m_fun(L
, boost::tuples::length
<Tuple
>::value
, 1))
134 assert(lua_gettop(L
) == top
- m_params
+ 1);
135 #ifndef LUABIND_NO_EXCEPTIONS
136 throw luabind::error(L
);
138 error_callback_fun e
= get_error_callback();
141 assert(0 && "the lua function threw an error and exceptions are disabled."
142 " If you want to handle the error you can use luabind::set_error_callback()");
147 // pops the return values from the function call
148 stack_pop
pop(L
, lua_gettop(L
) - top
+ m_params
);
150 if (converter
.match(L
, LUABIND_DECORATE_TYPE(Ret
), -1) < 0)
152 #ifndef LUABIND_NO_EXCEPTIONS
153 throw cast_failed(L
, typeid(Ret
));
155 cast_failed_callback_fun e
= get_cast_failed_callback();
156 if (e
) e(L
, typeid(Ret
));
158 assert(0 && "the lua function's return value could not be converted."
159 " If you want to handle the error you can use luabind::set_error_callback()");
163 return converter
.apply(L
, LUABIND_DECORATE_TYPE(Ret
), -1);
166 template<class Policies
>
167 Ret
operator[](const Policies
& p
)
169 typedef typename
detail::find_conversion_policy
<0, Policies
>::type converter_policy
;
170 typename
mpl::apply_wrap2
<converter_policy
,Ret
,lua_to_cpp
>::type converter
;
173 lua_State
* L
= m_state
;
175 int top
= lua_gettop(L
);
177 detail::push_args_from_tuple
<1>::apply(L
, m_args
, p
);
178 # ifdef LUABIND_CPP0x
179 if (m_fun(L
, std::tuple_size
<Tuple
>::value
, 1))
181 if (m_fun(L
, boost::tuples::length
<Tuple
>::value
, 1))
184 assert(lua_gettop(L
) == top
- m_params
+ 1);
185 #ifndef LUABIND_NO_EXCEPTIONS
188 error_callback_fun e
= get_error_callback();
191 assert(0 && "the lua function threw an error and exceptions are disabled."
192 " If you want to handle the error you can use luabind::set_error_callback()");
197 // pops the return values from the function call
198 stack_pop
pop(L
, lua_gettop(L
) - top
+ m_params
);
200 if (converter
.match(L
, LUABIND_DECORATE_TYPE(Ret
), -1) < 0)
202 #ifndef LUABIND_NO_EXCEPTIONS
203 throw cast_failed(L
, typeid(Ret
));
205 cast_failed_callback_fun e
= get_cast_failed_callback();
206 if (e
) e(L
, typeid(Ret
));
208 assert(0 && "the lua function's return value could not be converted."
209 " If you want to handle the error you can use luabind::set_error_callback()");
215 return converter
.apply(L
, LUABIND_DECORATE_TYPE(Ret
), -1);
224 mutable bool m_called
;
228 // if the proxy_member_caller returns void
229 template<class Tuple
>
230 class proxy_function_void_caller
234 typedef int(*function_t
)(lua_State
*, int, int);
236 proxy_function_void_caller(
249 proxy_function_void_caller(const proxy_function_void_caller
& rhs
)
250 : m_state(rhs
.m_state
)
251 , m_params(rhs
.m_params
)
254 , m_called(rhs
.m_called
)
259 ~proxy_function_void_caller()
261 if (m_called
) return;
264 lua_State
* L
= m_state
;
266 int top
= lua_gettop(L
);
268 push_args_from_tuple
<1>::apply(L
, m_args
);
269 # ifdef LUABIND_CPP0x
270 if (m_fun(L
, std::tuple_size
<Tuple
>::value
, 0))
272 if (m_fun(L
, boost::tuples::length
<Tuple
>::value
, 0))
275 assert(lua_gettop(L
) == top
- m_params
+ 1);
276 #ifndef LUABIND_NO_EXCEPTIONS
277 throw luabind::error(L
);
279 error_callback_fun e
= get_error_callback();
282 assert(0 && "the lua function threw an error and exceptions are disabled."
283 " If you want to handle the error you can use luabind::set_error_callback()");
287 // pops the return values from the function call
288 stack_pop
pop(L
, lua_gettop(L
) - top
+ m_params
);
291 template<class Policies
>
292 void operator[](const Policies
& p
)
295 lua_State
* L
= m_state
;
297 int top
= lua_gettop(L
);
299 detail::push_args_from_tuple
<1>::apply(L
, m_args
, p
);
300 # ifdef LUABIND_CPP0x
301 if (m_fun(L
, std::tuple_size
<Tuple
>::value
, 0))
303 if (m_fun(L
, boost::tuples::length
<Tuple
>::value
, 0))
306 assert(lua_gettop(L
) == top
- m_params
+ 1);
307 #ifndef LUABIND_NO_EXCEPTIONS
310 error_callback_fun e
= get_error_callback();
313 assert(0 && "the lua function threw an error and exceptions are disabled."
314 " If you want to handle the error you can use luabind::set_error_callback()");
318 // pops the return values from the function call
319 stack_pop
pop(L
, lua_gettop(L
) - top
+ m_params
);
328 mutable bool m_called
;
334 # ifdef LUABIND_CPP0x
340 template <class R
, class... Args
>
343 typedef proxy_function_caller
<R
, std::tuple
<Args
const*...> > type
;
346 template <class... Args
>
347 struct make_proxy
<void, Args
...>
349 typedef proxy_function_void_caller
<std::tuple
<Args
const*...> > type
;
352 } // namespace detail
354 template <class R
, class... Args
>
355 typename
detail::make_proxy
<R
, Args
...>::type
call_function(
356 lua_State
* L
, char const* name
, Args
const&... args
)
358 assert(name
&& "luabind::call_function() expects a function name");
360 lua_pushstring(L
, name
);
361 lua_gettable(L
, LUA_GLOBALSINDEX
);
363 typedef typename
detail::make_proxy
<R
, Args
...>::type proxy_type
;
364 return proxy_type(L
, 1, &detail::pcall
, std::tuple
<Args
const*...>(&args
...));
367 template <class R
, class... Args
>
368 typename
detail::make_proxy
<R
, Args
...>::type
call_function(
369 object
const& obj
, Args
const&... args
)
371 obj
.push(obj
.interpreter());
373 typedef typename
detail::make_proxy
<R
, Args
...>::type proxy_type
;
375 obj
.interpreter(), 1, &detail::pcall
, std::tuple
<Args
const*...>(&args
...));
378 template <class R
, class... Args
>
379 typename
detail::make_proxy
<R
, Args
...>::type
resume_function(
380 lua_State
* L
, char const* name
, Args
const&... args
)
382 assert(name
&& "luabind::call_function() expects a function name");
384 lua_pushstring(L
, name
);
385 lua_gettable(L
, LUA_GLOBALSINDEX
);
387 typedef typename
detail::make_proxy
<R
, Args
...>::type proxy_type
;
388 return proxy_type(L
, 1, &detail::resume_impl
, std::tuple
<Args
const*...>(&args
...));
391 template <class R
, class... Args
>
392 typename
detail::make_proxy
<R
, Args
...>::type
resume_function(
393 object
const& obj
, Args
const&... args
)
395 obj
.push(obj
.interpreter());
397 typedef typename
detail::make_proxy
<R
, Args
...>::type proxy_type
;
399 obj
.interpreter(), 1, &detail::resume_impl
, std::tuple
<Args
const*...>(&args
...));
402 template <class R
, class... Args
>
403 typename
detail::make_proxy
<R
, Args
...>::type
resume(
404 lua_State
* L
, Args
const&... args
)
406 typedef typename
detail::make_proxy
<R
, Args
...>::type proxy_type
;
408 L
, 0, &detail::resume_impl
, std::tuple
<Args
const*...>(&args
...));
411 # else // LUABIND_CPP0x
413 #define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, <luabind/detail/call_function.hpp>, 1))
414 #include BOOST_PP_ITERATE()
416 # endif // LUABIND_CPP0x
420 #endif // LUABIND_CALL_FUNCTION_HPP_INCLUDED
422 #elif BOOST_PP_ITERATION_FLAGS() == 1
424 #define LUABIND_TUPLE_PARAMS(z, n, data) const A##n *
425 #define LUABIND_OPERATOR_PARAMS(z, n, data) const A##n & a##n
428 template<class Ret
BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A
)>
429 typename
boost::mpl::if_
<boost::is_void
<Ret
>
430 , luabind::detail::proxy_function_void_caller
<boost::tuples::tuple
<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS
, _
)> >
431 , luabind::detail::proxy_function_caller
<Ret
, boost::tuples::tuple
<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS
, _
)> > >::type
432 call_function(lua_State
* L
, const char* name
BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_OPERATOR_PARAMS
, _
) )
434 assert(name
&& "luabind::call_function() expects a function name");
435 typedef boost::tuples::tuple
<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS
, _
)> tuple_t
;
436 #if BOOST_PP_ITERATION() == 0
439 tuple_t
args(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), &a
));
441 typedef typename
boost::mpl::if_
<boost::is_void
<Ret
>
442 , luabind::detail::proxy_function_void_caller
<boost::tuples::tuple
<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS
, _
)> >
443 , luabind::detail::proxy_function_caller
<Ret
, boost::tuples::tuple
<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS
, _
)> > >::type proxy_type
;
445 lua_pushstring(L
, name
);
446 lua_gettable(L
, LUA_GLOBALSINDEX
);
448 return proxy_type(L
, 1, &detail::pcall
, args
);
451 template<class Ret
BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A
)>
452 typename
boost::mpl::if_
<boost::is_void
<Ret
>
453 , luabind::detail::proxy_function_void_caller
<boost::tuples::tuple
<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS
, _
)> >
454 , luabind::detail::proxy_function_caller
<Ret
, boost::tuples::tuple
<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS
, _
)> > >::type
455 call_function(luabind::object
const& obj
BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_OPERATOR_PARAMS
, _
) )
457 typedef boost::tuples::tuple
<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS
, _
)> tuple_t
;
458 #if BOOST_PP_ITERATION() == 0
461 tuple_t
args(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), &a
));
463 typedef typename
boost::mpl::if_
<boost::is_void
<Ret
>
464 , luabind::detail::proxy_function_void_caller
<boost::tuples::tuple
<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS
, _
)> >
465 , luabind::detail::proxy_function_caller
<Ret
, boost::tuples::tuple
<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS
, _
)> > >::type proxy_type
;
467 obj
.push(obj
.interpreter());
468 return proxy_type(obj
.interpreter(), 1, &detail::pcall
, args
);
471 template<class Ret
BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A
)>
472 typename
boost::mpl::if_
<boost::is_void
<Ret
>
473 , luabind::detail::proxy_function_void_caller
<boost::tuples::tuple
<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS
, _
)> >
474 , luabind::detail::proxy_function_caller
<Ret
, boost::tuples::tuple
<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS
, _
)> > >::type
475 resume_function(lua_State
* L
, const char* name
BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_OPERATOR_PARAMS
, _
) )
477 assert(name
&& "luabind::resume_function() expects a function name");
478 typedef boost::tuples::tuple
<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS
, _
)> tuple_t
;
479 #if BOOST_PP_ITERATION() == 0
482 tuple_t
args(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), &a
));
484 typedef typename
boost::mpl::if_
<boost::is_void
<Ret
>
485 , luabind::detail::proxy_function_void_caller
<boost::tuples::tuple
<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS
, _
)> >
486 , luabind::detail::proxy_function_caller
<Ret
, boost::tuples::tuple
<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS
, _
)> > >::type proxy_type
;
488 lua_pushstring(L
, name
);
489 lua_gettable(L
, LUA_GLOBALSINDEX
);
491 return proxy_type(L
, 1, &detail::resume_impl
, args
);
494 template<class Ret
BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A
)>
495 typename
boost::mpl::if_
<boost::is_void
<Ret
>
496 , luabind::detail::proxy_function_void_caller
<boost::tuples::tuple
<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS
, _
)> >
497 , luabind::detail::proxy_function_caller
<Ret
, boost::tuples::tuple
<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS
, _
)> > >::type
498 resume_function(luabind::object
const& obj
BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_OPERATOR_PARAMS
, _
) )
500 typedef boost::tuples::tuple
<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS
, _
)> tuple_t
;
501 #if BOOST_PP_ITERATION() == 0
504 tuple_t
args(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), &a
));
506 typedef typename
boost::mpl::if_
<boost::is_void
<Ret
>
507 , luabind::detail::proxy_function_void_caller
<boost::tuples::tuple
<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS
, _
)> >
508 , luabind::detail::proxy_function_caller
<Ret
, boost::tuples::tuple
<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS
, _
)> > >::type proxy_type
;
510 obj
.push(obj
.interpreter());
511 return proxy_type(obj
.interpreter(), 1, &detail::resume_impl
, args
);
514 template<class Ret
BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A
)>
515 typename
boost::mpl::if_
<boost::is_void
<Ret
>
516 , luabind::detail::proxy_function_void_caller
<boost::tuples::tuple
<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS
, _
)> >
517 , luabind::detail::proxy_function_caller
<Ret
, boost::tuples::tuple
<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS
, _
)> > >::type
518 resume(lua_State
* L
BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_OPERATOR_PARAMS
, _
) )
520 typedef boost::tuples::tuple
<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS
, _
)> tuple_t
;
521 #if BOOST_PP_ITERATION() == 0
524 tuple_t
args(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), &a
));
526 typedef typename
boost::mpl::if_
<boost::is_void
<Ret
>
527 , luabind::detail::proxy_function_void_caller
<boost::tuples::tuple
<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS
, _
)> >
528 , luabind::detail::proxy_function_caller
<Ret
, boost::tuples::tuple
<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS
, _
)> > >::type proxy_type
;
530 return proxy_type(L
, 0, &detail::resume_impl
, args
);
534 #undef LUABIND_OPERATOR_PARAMS
535 #undef LUABIND_TUPLE_PARAMS