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_FUNCTION_HPP_INCLUDED
27 #define LUABIND_FUNCTION_HPP_INCLUDED
29 #include <luabind/prefix.hpp>
30 #include <luabind/config.hpp>
32 #include <boost/config.hpp>
33 #include <boost/preprocessor/repeat.hpp>
34 #include <boost/preprocessor/iteration/iterate.hpp>
35 #include <boost/preprocessor/repetition/enum.hpp>
36 #include <boost/preprocessor/repetition/enum_params.hpp>
37 #include <boost/preprocessor/cat.hpp>
39 #include <luabind/detail/signature_match.hpp>
40 #include <luabind/detail/call_function.hpp>
41 #include <luabind/detail/get_overload_signature.hpp>
42 #include <luabind/detail/overload_rep_base.hpp>
44 #include <luabind/scope.hpp>
51 namespace free_functions
54 struct overload_rep
: public overload_rep_base
57 #define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, <luabind/function.hpp>, 1))
58 #include BOOST_PP_ITERATE()
60 inline bool operator==(const overload_rep
& o
) const
62 if (o
.m_arity
!= m_arity
) return false;
63 if (o
.m_params_
.size() != m_params_
.size()) return false;
64 for (int i
= 0; i
< (int)m_params_
.size(); ++i
)
65 if (!(LUABIND_TYPE_INFO_EQUAL(m_params_
[i
], o
.m_params_
[i
]))) return false;
69 typedef int(*call_ptr
)(lua_State
*, void(*)());
71 inline void set_fun(call_ptr f
) { call_fun
= f
; }
72 inline int call(lua_State
* L
, void(*f
)()) const { return call_fun(L
, f
); }
74 // this is the actual function pointer to be called when this overload is invoked
81 // the types of the parameter it takes
82 std::vector
<LUABIND_TYPE_INFO
> m_params_
;
89 function_rep(const char* name
): m_name(name
) {}
90 void add_overload(const free_functions::overload_rep
& o
);
92 const std::vector
<overload_rep
>& overloads() const throw() { return m_overloads
; }
94 const char* name() const { return m_name
; }
99 // this have to be write protected, since each time an overload is
100 // added it has to be checked for existence. add_overload() should
102 std::vector
<free_functions::overload_rep
> m_overloads
;
107 // returns generates functions that calls function pointers
109 #define LUABIND_DECL(z, n, text) typedef typename find_conversion_policy<n + 1, Policies>::type BOOST_PP_CAT(converter_policy,n); \
110 typename BOOST_PP_CAT(converter_policy,n)::template generate_converter<A##n, lua_to_cpp>::type BOOST_PP_CAT(c,n);
112 #define LUABIND_ADD_INDEX(z,n,text) + BOOST_PP_CAT(converter_policy,n)::has_arg
113 #define LUABIND_INDEX_MAP(z,n,text) 1 BOOST_PP_REPEAT(n, LUABIND_ADD_INDEX, _)
114 #define LUABIND_PARAMS(z,n,text) BOOST_PP_CAT(c,n).apply(L, LUABIND_DECORATE_TYPE(A##n), LUABIND_INDEX_MAP(_,n,_))
115 #define LUABIND_POSTCALL(z,n,text) BOOST_PP_CAT(c,n).converter_postcall(L, LUABIND_DECORATE_TYPE(A##n), LUABIND_INDEX_MAP(_,n,_));
117 template<class Policies
>
120 static inline int apply(lua_State
* L
, int nret
)
122 return ret(L
, nret
, boost::mpl::bool_
<has_yield
<Policies
>::value
>());
125 static inline int ret(lua_State
* L
, int nret
, boost::mpl::bool_
<true>)
127 return lua_yield(L
, nret
);
130 static inline int ret(lua_State
*, int nret
, boost::mpl::bool_
<false>)
140 #define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, <luabind/function.hpp>, 2))
141 #include BOOST_PP_ITERATE()
147 #define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, <luabind/function.hpp>, 3))
148 #include BOOST_PP_ITERATE()
151 #define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, <luabind/function.hpp>, 4))
152 #include BOOST_PP_ITERATE()
155 #undef LUABIND_PARAMS
157 #undef LUABIND_POSTCALL
158 #undef LUABIND_ADD_INDEX
159 #undef LUABIND_INDEX_MAP
162 #define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, <luabind/function.hpp>, 5))
163 #include BOOST_PP_ITERATE()
166 template<class F
, class Policies
>
167 struct function_callback_s
169 static inline int apply(lua_State
* L
, void(*fun
)())
171 return free_functions::call(reinterpret_cast<F
>(fun
), L
, static_cast<const Policies
*>(0));
175 template<class F
, class Policies
>
176 struct match_function_callback_s
178 static inline int apply(lua_State
* L
)
181 return free_functions::match(fptr
, L
, static_cast<Policies
*>(0));
184 static int callback(lua_State
* L
)
187 return free_functions::match(fptr
, L
, static_cast<Policies
*>(0));
191 LUABIND_API
int function_dispatcher(lua_State
* L
);
196 template<class F
, class Policies
>
197 void function(lua_State
* L
, const char* name
, F f
, const Policies
& p
)
199 module(L
) [ def(name
, f
, p
) ];
204 void function(lua_State
* L
, const char* name
, F f
)
206 luabind::function(L
, name
, f
, detail::null_type());
211 template<class F
, class Policies
>
212 struct function_commiter
: detail::registration
214 function_commiter(const char* n
, F f
, const Policies
& p
)
220 virtual void register_(lua_State
* L
) const
222 detail::free_functions::overload_rep
o(fun
, static_cast<Policies
*>(0));
224 o
.set_match_fun(&detail::free_functions::match_function_callback_s
<F
, Policies
>::apply
);
225 o
.set_fun(&detail::free_functions::function_callback_s
<F
, Policies
>::apply
);
227 #ifndef LUABIND_NO_ERROR_CHECKING
228 o
.set_sig_fun(&detail::get_free_function_signature
<F
>::apply
);
231 lua_pushstring(L
, m_name
);
234 detail::free_functions::function_rep
* rep
= 0;
235 if (lua_iscfunction(L
, -1))
237 if (lua_getupvalue(L
, -1, 2) != 0)
239 // check the magic number that identifies luabind's functions
240 if (lua_touserdata(L
, -1) == (void*)0x1337)
242 if (lua_getupvalue(L
, -2, 1) != 0)
244 rep
= static_cast<detail::free_functions::function_rep
*>(lua_touserdata(L
, -1));
255 lua_pushstring(L
, m_name
);
256 // create a new function_rep
257 rep
= static_cast<detail::free_functions::function_rep
*>(lua_newuserdata(L
, sizeof(detail::free_functions::function_rep
)));
258 new(rep
) detail::free_functions::function_rep(m_name
);
261 lua_pushvalue(L
, -1);
264 detail::class_registry
* r
= detail::class_registry::get_registry(L
);
265 assert(r
&& "you must call luabind::open() prior to any function registrations");
266 detail::getref(L
, r
->lua_function());
267 int ret
= lua_setmetatable(L
, -2);
271 // this is just a magic number to identify functions that luabind created
272 lua_pushlightuserdata(L
, (void*)0x1337);
274 lua_pushcclosure(L
, &free_functions::function_dispatcher
, 2);
278 rep
->add_overload(o
);
287 template<class F
, class Policies
>
288 scope
def(const char* name
, F f
, const Policies
& policies
)
290 return scope(std::auto_ptr
<detail::registration
>(
291 new detail::function_commiter
<F
,Policies
>(name
, f
, policies
)));
295 scope
def(const char* name
, F f
)
297 return scope(std::auto_ptr
<detail::registration
>(
298 new detail::function_commiter
<F
,detail::null_type
>(
299 name
, f
, detail::null_type())));
302 } // namespace luabind
305 #endif // LUABIND_FUNCTION_HPP_INCLUDED
307 #elif BOOST_PP_ITERATION_FLAGS() == 1
309 // overloaded template funtion that initializes the parameter list
310 // called m_params and the m_arity member.
312 #define LUABIND_INIT_PARAM(z, n, _) m_params_.push_back(LUABIND_TYPEID(A##n));
313 #define LUABIND_POLICY_DECL(z,n,text) typedef typename find_conversion_policy<n + 1, Policies>::type BOOST_PP_CAT(p,n);
314 #define LUABIND_ARITY(z,n,text) + BOOST_PP_CAT(p,n)::has_arg
316 template<class R
BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A
), class Policies
>
317 overload_rep(R(*f
)(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), A
)), Policies
*)
318 : fun(reinterpret_cast<void(*)()>(f
))
320 m_params_
.reserve(BOOST_PP_ITERATION());
321 BOOST_PP_REPEAT(BOOST_PP_ITERATION(), LUABIND_INIT_PARAM
, _
)
322 BOOST_PP_REPEAT(BOOST_PP_ITERATION(), LUABIND_POLICY_DECL
, _
)
324 m_arity
= 0 BOOST_PP_REPEAT(BOOST_PP_ITERATION(), LUABIND_ARITY
, _
);
327 #undef LUABIND_INIT_PARAM
328 #undef LUABIND_POLICY_DECL
331 #elif BOOST_PP_ITERATION_FLAGS() == 2
333 template<class Policies
BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A
)>
334 static int call(T(*f
)(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), A
)), lua_State
* L
, const Policies
*)
336 /* typedef typename get_policy<0, Policies>::type ret_policy;
337 typedef typename ret_policy::head return_value_converter_intermediate;
338 typedef typename return_value_converter_intermediate::template generate_converter<T, cpp_to_lua>::type ret_conv;*/
340 int nargs
= lua_gettop(L
);
342 // typedef typename get_policy_list<0, Policies>::type policy_list_ret;
343 // typedef typename find_converter_policy<policy_list_ret>::type converter_policy_ret;
344 typedef typename find_conversion_policy
<0, Policies
>::type converter_policy_ret
;
345 typename
converter_policy_ret::template generate_converter
<T
, cpp_to_lua
>::type converter_ret
;
347 BOOST_PP_REPEAT(BOOST_PP_ITERATION(), LUABIND_DECL
, _
)
348 converter_ret
.apply(L
, f
350 BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_PARAMS
, _
)
352 BOOST_PP_REPEAT(BOOST_PP_ITERATION(), LUABIND_POSTCALL
, _
)
354 int nret
= lua_gettop(L
) - nargs
;
356 const int indices
[] =
359 nargs
+ nret
/* result*/
360 BOOST_PP_ENUM_TRAILING(BOOST_PP_ITERATION(), LUABIND_INDEX_MAP
, _
)
363 policy_list_postcall
<Policies
>::apply(L
, indices
);
365 return maybe_yield
<Policies
>::apply(L
, nret
);
370 #elif BOOST_PP_ITERATION_FLAGS() == 3
372 template<class Policies
BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A
)>
373 static int call(void(*f
)(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), A
)), lua_State
* L
, const Policies
*)
375 int nargs
= lua_gettop(L
);
377 BOOST_PP_REPEAT(BOOST_PP_ITERATION(), LUABIND_DECL
, _
)
380 BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_PARAMS
, _
)
382 BOOST_PP_REPEAT(BOOST_PP_ITERATION(), LUABIND_POSTCALL
, _
)
384 int nret
= lua_gettop(L
) - nargs
;
386 const int indices
[] =
389 nargs
+ nret
/* result*/
390 BOOST_PP_ENUM_TRAILING(BOOST_PP_ITERATION(), LUABIND_INDEX_MAP
, _
)
393 policy_list_postcall
<Policies
>::apply(L
, indices
);
395 return maybe_yield
<Policies
>::apply(L
, nret
);
399 #elif BOOST_PP_ITERATION_FLAGS() == 4
401 template<class Policies
, class R
BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A
)>
402 int call(R(*f
)(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), A
)), lua_State
* L
, const Policies
* policies
)
404 return free_functions::returns
<R
>::call(f
, L
, policies
);
407 #elif BOOST_PP_ITERATION_FLAGS() == 5
409 template<class Policies
, class R
BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A
)>
410 static int match(R(*)(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), A
)), lua_State
* L
, const Policies
* policies
)
412 //if (lua_gettop(L) != BOOST_PP_ITERATION()) return -1;
413 typedef constructor
<BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), A
)> ParameterTypes
;
414 return match_params(L
, 1, static_cast<ParameterTypes
*>(0), policies
);