Fix bug when passing type with holder by value to Lua.
[luabind.git] / luabind / detail / call.hpp
blob86e02a1fcaf31397a341e442637f0c9f36c849b3
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_HPP_INCLUDED
27 #define LUABIND_CALL_HPP_INCLUDED
29 #include <boost/config.hpp>
30 #include <boost/preprocessor/repeat.hpp>
31 #include <boost/preprocessor/iteration/iterate.hpp>
32 #include <boost/preprocessor/repetition/enum.hpp>
33 #include <boost/preprocessor/repetition/enum_params.hpp>
34 #include <boost/preprocessor/repetition/enum_trailing.hpp>
35 #include <boost/preprocessor/repetition/repeat.hpp>
36 #include <boost/preprocessor/punctuation/comma_if.hpp>
37 #include <boost/preprocessor/cat.hpp>
38 #include <boost/mpl/bool.hpp>
39 #include <boost/mpl/apply_wrap.hpp>
41 #include <luabind/config.hpp>
42 #include <luabind/detail/policy.hpp>
43 #include <luabind/yield_policy.hpp>
45 #include <luabind/detail/most_derived.hpp>
47 #define LUABIND_DECL(z, n, off) \
48 typedef typename find_conversion_policy< \
49 n + off \
50 , Policies \
51 >::type BOOST_PP_CAT(converter_policy,n); \
53 typename mpl::apply_wrap2< \
54 BOOST_PP_CAT(converter_policy,n), BOOST_PP_CAT(A,n), lua_to_cpp \
55 >::type BOOST_PP_CAT(c,n);
57 #define LUABIND_ADD_INDEX(z,n,text) \
58 + BOOST_PP_CAT(converter_policy,n)::has_arg
60 #define LUABIND_INDEX_MAP(z,n,text) \
61 text BOOST_PP_REPEAT(n, LUABIND_ADD_INDEX, _)
63 #define LUABIND_PARAMS(z,n,text) \
64 BOOST_PP_CAT(c,n).apply( \
65 L \
66 , LUABIND_DECORATE_TYPE(A##n) \
67 , LUABIND_INDEX_MAP(_,n,text) \
70 #define LUABIND_POSTCALL(z,n,text) \
71 BOOST_PP_CAT(c,n).converter_postcall( \
72 L \
73 , LUABIND_DECORATE_TYPE(A##n) \
74 , LUABIND_INDEX_MAP(_,n,text) \
77 namespace luabind { namespace detail
80 namespace mpl = boost::mpl;
82 template<class Policies>
83 struct maybe_yield
85 static inline int apply(lua_State* L, int nret)
87 return ret(L, nret, boost::mpl::bool_<has_yield<Policies>::value>());
90 static inline int ret(lua_State* L, int nret, boost::mpl::bool_<true>)
92 return lua_yield(L, nret);
95 static inline int ret(lua_State*, int nret, boost::mpl::bool_<false>)
97 return nret;
101 template<class T>
102 struct returns
104 #define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, <luabind/detail/call.hpp>, 1))
105 #include BOOST_PP_ITERATE()
108 template<>
109 struct returns<void>
111 #define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, <luabind/detail/call.hpp>, 2))
112 #include BOOST_PP_ITERATE()
115 #define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, <luabind/detail/call.hpp>, 3))
116 #include BOOST_PP_ITERATE()
119 #undef LUABIND_DECL
120 #undef LUABIND_PARAMS
121 #undef LUABIND_POSTCALL
122 #undef LUABIND_ADD_INDEX
123 #undef LUABIND_INDEX_MAP
125 #endif // LUABIND_CALL_HPP_INCLUDED
127 #elif BOOST_PP_ITERATION_FLAGS() == 1
129 template<
130 class C
131 , class WrappedClass
132 , class Policies
133 BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
134 BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A)
136 static int call(
137 T(C::*f)(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), A))
138 , WrappedClass*
139 , lua_State* L
140 , Policies const*)
142 int nargs = lua_gettop(L);
144 typedef typename most_derived<C, WrappedClass>::type self_type;
145 pointer_converter<lua_to_cpp> self_cv;
147 typedef typename find_conversion_policy<0, Policies>::type converter_policy_ret;
148 typename mpl::apply_wrap2<converter_policy_ret,T,cpp_to_lua>::type converter_ret;
150 BOOST_PP_REPEAT(BOOST_PP_ITERATION(), LUABIND_DECL, 2)
152 converter_ret.apply(
154 , (self_cv.apply(L, LUABIND_DECORATE_TYPE(self_type*), 1)->*f)
156 BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_PARAMS, 2)
159 BOOST_PP_REPEAT(BOOST_PP_ITERATION(), LUABIND_POSTCALL, 2)
161 int nret = lua_gettop(L) - nargs;
163 const int indices[] =
165 nargs + nret // result
166 , 1 // self
167 BOOST_PP_ENUM_TRAILING(BOOST_PP_ITERATION(), LUABIND_INDEX_MAP, 2)
170 policy_list_postcall<Policies>::apply(L, indices);
172 return maybe_yield<Policies>::apply(L, nret);
175 template<
176 class C
177 , class WrappedClass
178 , class Policies
179 BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
180 BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A)
182 static int call(
183 T(C::*f)(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), A)) const
184 , WrappedClass*
185 , lua_State* L
186 , Policies const*)
188 int nargs = lua_gettop(L);
190 typedef typename most_derived<C, WrappedClass>::type self_type;
191 const_pointer_converter<lua_to_cpp> self_cv;
193 typedef typename find_conversion_policy<0, Policies>::type converter_policy_ret;
194 typename mpl::apply_wrap2<converter_policy_ret,T,cpp_to_lua>::type converter_ret;
196 BOOST_PP_REPEAT(BOOST_PP_ITERATION(), LUABIND_DECL, 2)
198 converter_ret.apply(
200 , (self_cv.apply(L, LUABIND_DECORATE_TYPE(self_type const*), 1)->*f)
202 BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_PARAMS, 2)
205 BOOST_PP_REPEAT(BOOST_PP_ITERATION(), LUABIND_POSTCALL, 2)
206 int nret = lua_gettop(L) - nargs;
208 const int indices[] =
210 nargs + nret // result
211 , 1 // self
212 BOOST_PP_ENUM_TRAILING(BOOST_PP_ITERATION(), LUABIND_INDEX_MAP, 2)
215 policy_list_postcall<Policies>::apply(L, indices);
217 return maybe_yield<Policies>::apply(L, nret);
220 template<
221 class WrappedClass
222 , class Policies
223 BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
224 BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A)
226 static int call(
227 T(*f)(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), A))
228 , WrappedClass*
229 , lua_State* L
230 , Policies const*)
232 int nargs = lua_gettop(L);
233 typedef typename find_conversion_policy<0, Policies>::type converter_policy_ret;
234 typename mpl::apply_wrap2<converter_policy_ret,T,cpp_to_lua>::type converter_ret;
235 BOOST_PP_REPEAT(BOOST_PP_ITERATION(), LUABIND_DECL, 1)
236 converter_ret.apply(L, f
238 BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_PARAMS, 1)
241 BOOST_PP_REPEAT(BOOST_PP_ITERATION(), LUABIND_POSTCALL, 1)
243 int nret = lua_gettop(L) - nargs;
245 const int indices[] =
247 nargs + nret // result
248 BOOST_PP_ENUM_TRAILING(BOOST_PP_ITERATION(), LUABIND_INDEX_MAP, 1)
251 policy_list_postcall<Policies>::apply(L, indices);
253 return maybe_yield<Policies>::apply(L, nret);
256 #elif BOOST_PP_ITERATION_FLAGS() == 2
258 template<
259 class C
260 , class WrappedClass
261 , class Policies
262 BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
263 BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A)
265 static int call(
266 void(C::*f)(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), A))
267 , WrappedClass*
268 , lua_State* L
269 , Policies* const)
271 int nargs = lua_gettop(L);
272 L = L; // L is used, but metrowerks compiler seem to warn about it before expanding the macros
274 typedef typename most_derived<C, WrappedClass>::type self_type;
275 pointer_converter<lua_to_cpp> self_cv;
277 BOOST_PP_REPEAT(BOOST_PP_ITERATION(), LUABIND_DECL, 2)
278 (self_cv.apply(L, LUABIND_DECORATE_TYPE(self_type*), 1)->*f)
280 BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_PARAMS, 2)
282 BOOST_PP_REPEAT(BOOST_PP_ITERATION(), LUABIND_POSTCALL, 2)
284 int nret = lua_gettop(L) - nargs;
286 const int indices[] =
288 nargs + nret // result
289 , 1 // self
290 BOOST_PP_ENUM_TRAILING(BOOST_PP_ITERATION(), LUABIND_INDEX_MAP, 2)
293 policy_list_postcall<Policies>::apply(L, indices);
295 return maybe_yield<Policies>::apply(L, nret);
298 template<
299 class C
300 , class WrappedClass
301 , class Policies
302 BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
303 BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A)
305 static int call(
306 void(C::*f)(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), A)) const
307 , WrappedClass*
308 , lua_State* L
309 , Policies const*)
311 int nargs = lua_gettop(L);
312 L = L; // L is used, but metrowerks compiler seem to warn about it before expanding the macros
314 typedef typename most_derived<C, WrappedClass>::type self_type;
315 const_pointer_converter<lua_to_cpp> self_cv;
317 BOOST_PP_REPEAT(BOOST_PP_ITERATION(), LUABIND_DECL, 2)
318 (self_cv.apply(L, LUABIND_DECORATE_TYPE(self_type const*), 1)->*f)
320 BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_PARAMS, 2)
322 BOOST_PP_REPEAT(BOOST_PP_ITERATION(), LUABIND_POSTCALL, 2)
324 int nret = lua_gettop(L) - nargs;
326 const int indices[] =
328 nargs + nret // result
329 , 1 // self
330 BOOST_PP_ENUM_TRAILING(BOOST_PP_ITERATION(), LUABIND_INDEX_MAP, 2)
333 policy_list_postcall<Policies>::apply(L, indices);
335 return maybe_yield<Policies>::apply(L, nret);
338 template<
339 class WrappedClass
340 , class Policies
341 BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
342 BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A)
344 static int call(
345 void(*f)(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), A))
346 , WrappedClass*
347 , lua_State* L
348 , Policies const*)
350 int nargs = lua_gettop(L);
351 L = L; // L is used, but metrowerks compiler seem to warn about it before expanding the macros
352 BOOST_PP_REPEAT(BOOST_PP_ITERATION(), LUABIND_DECL, 1)
354 BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_PARAMS, 1)
357 int nret = lua_gettop(L) - nargs;
359 const int indices[] =
361 nargs + nret /* result */
362 BOOST_PP_ENUM_TRAILING(BOOST_PP_ITERATION(), LUABIND_INDEX_MAP, 1)
364 BOOST_PP_REPEAT(BOOST_PP_ITERATION(), LUABIND_POSTCALL, 1)
366 policy_list_postcall<Policies>::apply(L, indices);
368 return maybe_yield<Policies>::apply(L, nret);
371 #elif BOOST_PP_ITERATION_FLAGS() == 3
373 template<
374 class WrappedClass
375 , class Policies
376 , class R
377 BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
378 BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A)
380 int call(
381 R(*f)(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), A))
382 , WrappedClass*
383 , lua_State* L
384 , Policies const*)
386 return returns<R>::call(f, (WrappedClass*)0, L, (Policies*)0);
389 template<
390 class T
391 , class WrappedClass
392 , class Policies
393 , class R
394 BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
395 BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A)
397 int call(
398 R(T::*f)(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), A))
399 , WrappedClass*
400 , lua_State* L
401 , Policies const*)
403 return returns<R>::call(f, (WrappedClass*)0, L, (Policies*)0);
406 template<
407 class T
408 , class WrappedClass
409 , class Policies
410 , class R
411 BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
412 BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A)
414 int call(
415 R(T::*f)(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), A)) const
416 , WrappedClass*
417 , lua_State* L
418 , Policies const*)
420 return returns<R>::call(f, (WrappedClass*)0, L, (Policies*)0);
423 #endif