Test object identity with shared_ptr_converter.
[luabind.git] / luabind / detail / call_function.hpp
blob1b45ec15723fc8adf5f7b48e4c33853d4d9ba8cf
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>
45 namespace luabind
47 namespace detail
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;
55 public:
57 typedef int(*function_t)(lua_State*, int, int);
59 proxy_function_caller(
60 lua_State* L
61 , int params
62 , function_t fun
63 , const Tuple args)
64 : m_state(L)
65 , m_params(params)
66 , m_fun(fun)
67 , m_args(args)
68 , m_called(false)
72 proxy_function_caller(const proxy_function_caller& rhs)
73 : m_state(rhs.m_state)
74 , m_params(rhs.m_params)
75 , m_fun(rhs.m_fun)
76 , m_args(rhs.m_args)
77 , m_called(rhs.m_called)
79 rhs.m_called = true;
82 ~proxy_function_caller()
84 if (m_called) return;
86 m_called = true;
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);
97 #else
98 error_callback_fun e = get_error_callback();
99 if (e) e(L);
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()");
103 std::terminate();
105 #endif
108 // pops the return values from the function call
109 stack_pop pop(L, lua_gettop(L) - top + m_params);
112 operator Ret()
114 typename mpl::apply_wrap2<default_policy,Ret,lua_to_cpp>::type converter;
116 m_called = true;
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);
127 #else
128 error_callback_fun e = get_error_callback();
129 if (e) e(L);
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()");
133 std::terminate();
134 #endif
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, typeid(Ret));
146 #else
147 cast_failed_callback_fun e = get_cast_failed_callback();
148 if (e) e(L, 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()");
152 std::terminate();
154 #endif
156 #endif
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;
166 m_called = true;
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
176 throw error(L);
177 #else
178 error_callback_fun e = get_error_callback();
179 if (e) e(L);
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()");
183 std::terminate();
184 #endif
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, typeid(Ret));
196 #else
197 cast_failed_callback_fun e = get_cast_failed_callback();
198 if (e) e(L, 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()");
202 std::terminate();
204 #endif
206 #endif
207 return converter.apply(L, LUABIND_DECORATE_TYPE(Ret), -1);
210 private:
212 lua_State* m_state;
213 int m_params;
214 function_t m_fun;
215 Tuple m_args;
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;
225 public:
227 typedef int(*function_t)(lua_State*, int, int);
229 proxy_function_void_caller(
230 lua_State* L
231 , int params
232 , function_t fun
233 , const Tuple args)
234 : m_state(L)
235 , m_params(params)
236 , m_fun(fun)
237 , m_args(args)
238 , m_called(false)
242 proxy_function_void_caller(const proxy_function_void_caller& rhs)
243 : m_state(rhs.m_state)
244 , m_params(rhs.m_params)
245 , m_fun(rhs.m_fun)
246 , m_args(rhs.m_args)
247 , m_called(rhs.m_called)
249 rhs.m_called = true;
252 ~proxy_function_void_caller()
254 if (m_called) return;
256 m_called = true;
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);
267 #else
268 error_callback_fun e = get_error_callback();
269 if (e) e(L);
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()");
273 std::terminate();
274 #endif
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)
283 m_called = true;
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
293 throw error(L);
294 #else
295 error_callback_fun e = get_error_callback();
296 if (e) e(L);
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()");
300 std::terminate();
301 #endif
303 // pops the return values from the function call
304 stack_pop pop(L, lua_gettop(L) - top + m_params);
307 private:
309 lua_State* m_state;
310 int m_params;
311 function_t m_fun;
312 Tuple m_args;
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
341 tuple_t args;
342 #else
343 tuple_t args(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), &a));
344 #endif
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
363 tuple_t args;
364 #else
365 tuple_t args(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), &a));
366 #endif
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
384 tuple_t args;
385 #else
386 tuple_t args(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), &a));
387 #endif
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
406 tuple_t args;
407 #else
408 tuple_t args(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), &a));
409 #endif
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
426 tuple_t args;
427 #else
428 tuple_t args(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), &a));
429 #endif
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
442 #endif