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>
34 #include <boost/preprocessor/repeat.hpp>
35 #include <boost/preprocessor/iteration/iterate.hpp>
36 #include <boost/preprocessor/repetition/enum.hpp>
37 #include <boost/preprocessor/repetition/enum_params.hpp>
38 #include <boost/preprocessor/repetition/enum_binary_params.hpp>
39 #include <boost/preprocessor/punctuation/comma_if.hpp>
41 #include <luabind/error.hpp>
42 #include <luabind/detail/convert_to_lua.hpp>
43 #include <luabind/detail/pcall.hpp>
50 // if the proxy_function_caller returns non-void
51 template<class Ret
, class Tuple
>
52 class proxy_function_caller
54 // friend class luabind::object;
57 typedef int(*function_t
)(lua_State
*, int, int);
59 proxy_function_caller(
72 proxy_function_caller(const proxy_function_caller
& rhs
)
73 : m_state(rhs
.m_state
)
74 , m_params(rhs
.m_params
)
77 , m_called(rhs
.m_called
)
82 ~proxy_function_caller()
87 lua_State
* L
= m_state
;
89 int top
= lua_gettop(L
);
91 push_args_from_tuple
<1>::apply(L
, m_args
);
92 if (m_fun(L
, boost::tuples::length
<Tuple
>::value
, 0))
94 assert(lua_gettop(L
) == top
- m_params
+ 1);
95 #ifndef LUABIND_NO_EXCEPTIONS
96 throw luabind::error(L
);
98 error_callback_fun e
= get_error_callback();
101 assert(0 && "the lua function threw an error and exceptions are disabled."
102 " If you want to handle the error you can use luabind::set_error_callback()");
108 // pops the return values from the function call
109 stack_pop
pop(L
, lua_gettop(L
) - top
+ m_params
);
114 typename
mpl::apply_wrap2
<default_policy
,Ret
,lua_to_cpp
>::type converter
;
117 lua_State
* L
= m_state
;
119 int top
= lua_gettop(L
);
121 push_args_from_tuple
<1>::apply(L
, m_args
);
122 if (m_fun(L
, boost::tuples::length
<Tuple
>::value
, 1))
124 assert(lua_gettop(L
) == top
- m_params
+ 1);
125 #ifndef LUABIND_NO_EXCEPTIONS
126 throw luabind::error(L
);
128 error_callback_fun e
= get_error_callback();
131 assert(0 && "the lua function threw an error and exceptions are disabled."
132 " If you want to handle the error you can use luabind::set_error_callback()");
137 // pops the return values from the function call
138 stack_pop
pop(L
, lua_gettop(L
) - top
+ m_params
);
140 #ifndef LUABIND_NO_ERROR_CHECKING
142 if (converter
.match(L
, LUABIND_DECORATE_TYPE(Ret
), -1) < 0)
144 #ifndef LUABIND_NO_EXCEPTIONS
145 throw cast_failed(L
, LUABIND_TYPEID(Ret
));
147 cast_failed_callback_fun e
= get_cast_failed_callback();
148 if (e
) e(L
, LUABIND_TYPEID(Ret
));
150 assert(0 && "the lua function's return value could not be converted."
151 " If you want to handle the error you can use luabind::set_error_callback()");
157 return converter
.apply(L
, LUABIND_DECORATE_TYPE(Ret
), -1);
160 template<class Policies
>
161 Ret
operator[](const Policies
& p
)
163 typedef typename
detail::find_conversion_policy
<0, Policies
>::type converter_policy
;
164 typename
mpl::apply_wrap2
<converter_policy
,Ret
,lua_to_cpp
>::type converter
;
167 lua_State
* L
= m_state
;
169 int top
= lua_gettop(L
);
171 detail::push_args_from_tuple
<1>::apply(L
, m_args
, p
);
172 if (m_fun(L
, boost::tuples::length
<Tuple
>::value
, 1))
174 assert(lua_gettop(L
) == top
- m_params
+ 1);
175 #ifndef LUABIND_NO_EXCEPTIONS
178 error_callback_fun e
= get_error_callback();
181 assert(0 && "the lua function threw an error and exceptions are disabled."
182 " If you want to handle the error you can use luabind::set_error_callback()");
187 // pops the return values from the function call
188 stack_pop
pop(L
, lua_gettop(L
) - top
+ m_params
);
190 #ifndef LUABIND_NO_ERROR_CHECKING
192 if (converter
.match(L
, LUABIND_DECORATE_TYPE(Ret
), -1) < 0)
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 the error you can use luabind::set_error_callback()");
207 return converter
.apply(L
, LUABIND_DECORATE_TYPE(Ret
), -1);
216 mutable bool m_called
;
220 // if the proxy_member_caller returns void
221 template<class Tuple
>
222 class proxy_function_void_caller
224 friend class luabind::object
;
227 typedef int(*function_t
)(lua_State
*, int, int);
229 proxy_function_void_caller(
242 proxy_function_void_caller(const proxy_function_void_caller
& rhs
)
243 : m_state(rhs
.m_state
)
244 , m_params(rhs
.m_params
)
247 , m_called(rhs
.m_called
)
252 ~proxy_function_void_caller()
254 if (m_called
) return;
257 lua_State
* L
= m_state
;
259 int top
= lua_gettop(L
);
261 push_args_from_tuple
<1>::apply(L
, m_args
);
262 if (m_fun(L
, boost::tuples::length
<Tuple
>::value
, 0))
264 assert(lua_gettop(L
) == top
- m_params
+ 1);
265 #ifndef LUABIND_NO_EXCEPTIONS
266 throw luabind::error(L
);
268 error_callback_fun e
= get_error_callback();
271 assert(0 && "the lua function threw an error and exceptions are disabled."
272 " If you want to handle the error you can use luabind::set_error_callback()");
276 // pops the return values from the function call
277 stack_pop
pop(L
, lua_gettop(L
) - top
+ m_params
);
280 template<class Policies
>
281 void operator[](const Policies
& p
)
284 lua_State
* L
= m_state
;
286 int top
= lua_gettop(L
);
288 detail::push_args_from_tuple
<1>::apply(L
, m_args
, p
);
289 if (m_fun(L
, boost::tuples::length
<Tuple
>::value
, 0))
291 assert(lua_gettop(L
) == top
- m_params
+ 1);
292 #ifndef LUABIND_NO_EXCEPTIONS
295 error_callback_fun e
= get_error_callback();
298 assert(0 && "the lua function threw an error and exceptions are disabled."
299 " If you want to handle the error you can use luabind::set_error_callback()");
303 // pops the return values from the function call
304 stack_pop
pop(L
, lua_gettop(L
) - top
+ m_params
);
313 mutable bool m_called
;
319 #define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, <luabind/detail/call_function.hpp>, 1))
320 #include BOOST_PP_ITERATE()
324 #endif // LUABIND_CALL_FUNCTION_HPP_INCLUDED
326 #elif BOOST_PP_ITERATION_FLAGS() == 1
328 #define LUABIND_TUPLE_PARAMS(z, n, data) const A##n *
329 #define LUABIND_OPERATOR_PARAMS(z, n, data) const A##n & a##n
332 template<class Ret
BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A
)>
333 typename
boost::mpl::if_
<boost::is_void
<Ret
>
334 , luabind::detail::proxy_function_void_caller
<boost::tuples::tuple
<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS
, _
)> >
335 , luabind::detail::proxy_function_caller
<Ret
, boost::tuples::tuple
<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS
, _
)> > >::type
336 call_function(lua_State
* L
, const char* name
BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_OPERATOR_PARAMS
, _
) )
338 assert(name
&& "luabind::call_function() expects a function name");
339 typedef boost::tuples::tuple
<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS
, _
)> tuple_t
;
340 #if BOOST_PP_ITERATION() == 0
343 tuple_t
args(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), &a
));
345 typedef typename
boost::mpl::if_
<boost::is_void
<Ret
>
346 , luabind::detail::proxy_function_void_caller
<boost::tuples::tuple
<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS
, _
)> >
347 , luabind::detail::proxy_function_caller
<Ret
, boost::tuples::tuple
<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS
, _
)> > >::type proxy_type
;
349 lua_pushstring(L
, name
);
350 lua_gettable(L
, LUA_GLOBALSINDEX
);
352 return proxy_type(L
, 1, &detail::pcall
, args
);
355 template<class Ret
BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A
)>
356 typename
boost::mpl::if_
<boost::is_void
<Ret
>
357 , luabind::detail::proxy_function_void_caller
<boost::tuples::tuple
<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS
, _
)> >
358 , luabind::detail::proxy_function_caller
<Ret
, boost::tuples::tuple
<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS
, _
)> > >::type
359 call_function(luabind::object
const& obj
BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_OPERATOR_PARAMS
, _
) )
361 typedef boost::tuples::tuple
<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS
, _
)> tuple_t
;
362 #if BOOST_PP_ITERATION() == 0
365 tuple_t
args(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), &a
));
367 typedef typename
boost::mpl::if_
<boost::is_void
<Ret
>
368 , luabind::detail::proxy_function_void_caller
<boost::tuples::tuple
<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS
, _
)> >
369 , luabind::detail::proxy_function_caller
<Ret
, boost::tuples::tuple
<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS
, _
)> > >::type proxy_type
;
371 obj
.push(obj
.interpreter());
372 return proxy_type(obj
.interpreter(), 1, &detail::pcall
, args
);
375 template<class Ret
BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A
)>
376 typename
boost::mpl::if_
<boost::is_void
<Ret
>
377 , luabind::detail::proxy_function_void_caller
<boost::tuples::tuple
<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS
, _
)> >
378 , luabind::detail::proxy_function_caller
<Ret
, boost::tuples::tuple
<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS
, _
)> > >::type
379 resume_function(lua_State
* L
, const char* name
BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_OPERATOR_PARAMS
, _
) )
381 assert(name
&& "luabind::resume_function() expects a function name");
382 typedef boost::tuples::tuple
<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS
, _
)> tuple_t
;
383 #if BOOST_PP_ITERATION() == 0
386 tuple_t
args(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), &a
));
388 typedef typename
boost::mpl::if_
<boost::is_void
<Ret
>
389 , luabind::detail::proxy_function_void_caller
<boost::tuples::tuple
<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS
, _
)> >
390 , luabind::detail::proxy_function_caller
<Ret
, boost::tuples::tuple
<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS
, _
)> > >::type proxy_type
;
392 lua_pushstring(L
, name
);
393 lua_gettable(L
, LUA_GLOBALSINDEX
);
395 return proxy_type(L
, 1, &detail::resume_impl
, args
);
398 template<class Ret
BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A
)>
399 typename
boost::mpl::if_
<boost::is_void
<Ret
>
400 , luabind::detail::proxy_function_void_caller
<boost::tuples::tuple
<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS
, _
)> >
401 , luabind::detail::proxy_function_caller
<Ret
, boost::tuples::tuple
<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS
, _
)> > >::type
402 resume_function(luabind::object
const& obj
BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_OPERATOR_PARAMS
, _
) )
404 typedef boost::tuples::tuple
<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS
, _
)> tuple_t
;
405 #if BOOST_PP_ITERATION() == 0
408 tuple_t
args(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), &a
));
410 typedef typename
boost::mpl::if_
<boost::is_void
<Ret
>
411 , luabind::detail::proxy_function_void_caller
<boost::tuples::tuple
<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS
, _
)> >
412 , luabind::detail::proxy_function_caller
<Ret
, boost::tuples::tuple
<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS
, _
)> > >::type proxy_type
;
414 obj
.push(obj
.interpreter());
415 return proxy_type(obj
.interpreter(), 1, &detail::resume_impl
, args
);
418 template<class Ret
BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A
)>
419 typename
boost::mpl::if_
<boost::is_void
<Ret
>
420 , luabind::detail::proxy_function_void_caller
<boost::tuples::tuple
<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS
, _
)> >
421 , luabind::detail::proxy_function_caller
<Ret
, boost::tuples::tuple
<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS
, _
)> > >::type
422 resume(lua_State
* L
BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_OPERATOR_PARAMS
, _
) )
424 typedef boost::tuples::tuple
<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS
, _
)> tuple_t
;
425 #if BOOST_PP_ITERATION() == 0
428 tuple_t
args(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), &a
));
430 typedef typename
boost::mpl::if_
<boost::is_void
<Ret
>
431 , luabind::detail::proxy_function_void_caller
<boost::tuples::tuple
<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS
, _
)> >
432 , luabind::detail::proxy_function_caller
<Ret
, boost::tuples::tuple
<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS
, _
)> > >::type proxy_type
;
434 return proxy_type(L
, 0, &detail::resume_impl
, args
);
438 #undef LUABIND_OPERATOR_PARAMS
439 #undef LUABIND_TUPLE_PARAMS