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_FUNCTIONS_HPP_INCLUDED
27 #define LUABIND_FUNCTIONS_HPP_INCLUDED
29 #include <luabind/config.hpp>
31 #include <boost/config.hpp>
32 #include <boost/preprocessor/repeat.hpp>
33 #include <boost/preprocessor/iteration/iterate.hpp>
34 #include <boost/preprocessor/repetition/enum.hpp>
35 #include <boost/preprocessor/repetition/enum_params.hpp>
36 #include <boost/preprocessor/cat.hpp>
38 #include <luabind/detail/signature_match.hpp>
39 #include <luabind/detail/call_function.hpp>
40 #include <luabind/detail/get_overload_signature.hpp>
41 #include <luabind/detail/overload_rep_base.hpp>
48 namespace free_functions
51 struct overload_rep
: public overload_rep_base
54 #define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, <luabind/function.hpp>, 1))
55 #include BOOST_PP_ITERATE()
57 inline bool operator==(const overload_rep
& o
) const
59 if (o
.m_arity
!= m_arity
) return false;
60 if (o
.m_num_args
!= m_num_args
) return false;
61 for (int i
= 0; i
< m_num_args
; ++i
)
62 if (!(LUABIND_TYPE_INFO_EQUAL(m_params
[i
], o
.m_params
[i
]))) return false;
66 typedef int(*call_ptr
)(lua_State
*, void(*)());
68 inline void set_fun(call_ptr f
) { call_fun
= f
; }
69 inline int call(lua_State
* L
, void(*f
)()) const { return call_fun(L
, f
); }
71 // this is the actual function pointer to be called when this overload is invoked
79 // the number of parameters this overload takes
80 // these are used to detect when a function by a derived class.
82 // the types of the parameter it takes
83 LUABIND_TYPE_INFO m_params
[LUABIND_MAX_ARITY
];
91 void add_overload(const free_functions::overload_rep
& o
)
93 std::vector
<free_functions::overload_rep
>::iterator i
= std::find(m_overloads
.begin(), m_overloads
.end(), o
);
95 // if the overload already exists, overwrite the existing function
96 if (i
!= m_overloads
.end())
102 m_overloads
.push_back(o
);
106 const std::vector
<overload_rep
>& overloads() const throw() { return m_overloads
; }
108 #ifdef LUABIND_DONT_COPY_STRINGS
115 // this have to be write protected, since each time an overload is
116 // added it has to be checked for existence. add_overload() should
118 std::vector
<free_functions::overload_rep
> m_overloads
;
123 // returns generates functions that calls function pointers
125 #define LUABIND_DECL(z, n, text) typedef typename detail::get_policy<n+1,Policies>::type BOOST_PP_CAT(a##n,_policy); \
126 typedef typename BOOST_PP_CAT(a##n,_policy)::head BOOST_PP_CAT(a##n,_param_converter_intermediate); \
127 typedef typename BOOST_PP_CAT(a##n,_param_converter_intermediate)::template generate_converter<A##n, lua_to_cpp>::type BOOST_PP_CAT(p##n,_conv);
129 #define LUABIND_PARAMS(z,n,text) BOOST_PP_CAT(p##n,_conv)::apply(L, LUABIND_DECORATE_TYPE(A##n), n + 1)
132 #define LUABIND_DECL(z, n, text) typedef typename find_conversion_policy<n + 1, Policies>::type BOOST_PP_CAT(converter_policy,n); \
133 typename BOOST_PP_CAT(converter_policy,n)::template generate_converter<A##n, lua_to_cpp>::type BOOST_PP_CAT(c,n);
135 #define LUABIND_ADD_INDEX(z,n,text) + BOOST_PP_CAT(converter_policy,n)::has_arg
136 #define LUABIND_INDEX_MAP(z,n,text) 1 BOOST_PP_REPEAT(n, LUABIND_ADD_INDEX, _)
137 #define LUABIND_PARAMS(z,n,text) BOOST_PP_CAT(c,n).apply(L, LUABIND_DECORATE_TYPE(A##n), LUABIND_INDEX_MAP(_,n,_))
138 #define LUABIND_POSTCALL(z,n,text) BOOST_PP_CAT(c,n).converter_postcall(L, LUABIND_DECORATE_TYPE(A##n), LUABIND_INDEX_MAP(_,n,_));
143 #define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, <luabind/function.hpp>, 2))
144 #include BOOST_PP_ITERATE()
150 #define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, <luabind/function.hpp>, 3))
151 #include BOOST_PP_ITERATE()
154 #define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, <luabind/function.hpp>, 4))
155 #include BOOST_PP_ITERATE()
158 #undef LUABIND_PARAMS
160 #undef LUABIND_POSTCALL
161 #undef LUABIND_ADD_INDEX
162 #undef LUABIND_INDEX_MAP
165 #define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, <luabind/function.hpp>, 5))
166 #include BOOST_PP_ITERATE()
171 struct function_registry
173 std::map
<const char*, free_functions::function_rep
, ltstr
> m_functions
;
174 #ifndef LUABIND_DONT_COPY_STRINGS
175 std::vector
<char*> m_strings
;
179 for (std::vector
<char*>::iterator i
= m_strings
.begin(); i
!= m_strings
.end(); ++i
)
185 template<class F
, class Policies
>
186 struct function_callback_s
188 static inline int apply(lua_State
* L
, void(*fun
)())
190 return free_functions::call(reinterpret_cast<F
>(fun
), L
, static_cast<const Policies
*>(0));
194 template<class F
, class Policies
>
195 struct match_function_callback_s
197 static inline int apply(lua_State
* L
)
200 return free_functions::match(fptr
, L
, static_cast<Policies
*>(0));
203 static int callback(lua_State
* L
)
206 return free_functions::match(fptr
, L
, static_cast<Policies
*>(0));
210 inline int function_dispatcher(lua_State
* L
)
212 function_rep
* rep
= static_cast<function_rep
*>(lua_touserdata(L
, lua_upvalueindex(1)));
214 bool ambiguous
= false;
215 int min_match
= std::numeric_limits
<int>::max();
216 int match_index
= -1;
219 #ifdef LUABIND_NO_ERROR_CHECKING
221 if (rep
->overloads().size() == 1)
229 int num_params
= lua_gettop(L
);
230 ret
= find_best_match(L
, rep
->overloads().begin(), rep
->overloads().end(), ambiguous
, min_match
, match_index
, num_params
);
232 #ifdef LUABIND_NO_ERROR_CHECKING
239 // this bock is needed to make sure the std::string is destructed
241 std::string msg
= "no match for function call '";
243 msg
+= "' with the parameters (";
244 msg
+= stack_content_by_name(L
, 1);
245 msg
+= ")\ncandidates are:\n";
247 msg
+= get_overload_signatures(L
, rep
->overloads().begin(), rep
->overloads().end(), rep
->name
);
249 lua_pushstring(L
, msg
.c_str());
256 // this bock is needed to make sure the std::string is destructed
258 std::string msg
= "call of overloaded function '";
261 msg
+= stack_content_by_name(L
, 1);
262 msg
+= ") is ambiguous\nnone of the overloads have a best conversion:";
264 std::vector
<free_functions::overload_rep
> candidates
;
265 find_exact_match(L
, rep
->overloads().begin(), rep
->overloads().end(), min_match
, num_params
, candidates
);
267 msg
+= get_overload_signatures(L
, candidates
.begin(), candidates
.end(), rep
->name
);
269 lua_pushstring(L
, msg
.c_str());
274 const overload_rep
& ov_rep
= rep
->overloads()[match_index
];
275 return ov_rep
.call(L
, ov_rep
.fun
);
280 template<class F
, class Policies
>
281 void function(lua_State
* L
, const char* name
, F f
, const Policies
&)
283 detail::free_functions::function_registry
* registry
= 0;
284 lua_pushstring(L
, "__lua_free_functions");
285 lua_gettable(L
, LUA_REGISTRYINDEX
);
287 registry
= static_cast<detail::free_functions::function_registry
*>(lua_touserdata(L
, -1));
290 // if you hit this assert you have not called luabind::open() for
291 // this lua_State. See the documentation for more information.
292 assert(registry
!= 0);
294 #ifdef LUABIND_DONT_COPY_STRINGS
295 detail::free_functions::function_rep
& rep
= registry
->m_functions
[name
];
297 registry
->m_strings
.push_back(detail::dup_string(name
));
298 detail::free_functions::function_rep
& rep
= registry
->m_functions
[registry
->m_strings
.back()];
301 detail::free_functions::overload_rep
o(f
, static_cast<Policies
*>(0));
303 o
.set_match_fun(&detail::free_functions::match_function_callback_s
<F
, Policies
>::apply
);
304 o
.set_fun(&detail::free_functions::function_callback_s
<F
, Policies
>::apply
);
306 #ifndef LUABIND_NO_ERROR_CHECKING
307 o
.set_sig_fun(&detail::get_free_function_signature
<F
>::apply
);
313 lua_pushstring(L
, name
);
314 lua_pushlightuserdata(L
, &rep
);
315 lua_pushcclosure(L
, detail::free_functions::function_dispatcher
, 1);
316 lua_settable(L
, LUA_GLOBALSINDEX
);
320 void function(lua_State
* L
, const char* name
, F f
)
322 luabind::function(L
, name
, f
, detail::null_type());
325 } // namespace luabind
328 #endif // LUABIND_FUNCTION_HPP_INCLUDED
330 #elif BOOST_PP_ITERATION_FLAGS() == 1
332 // overloaded template funtion that initializes the parameter list
333 // called m_params and the m_arity member.
335 #define LUABIND_INIT_PARAM(z, n, _) m_params[n] = LUABIND_TYPEID(A##n);
336 #define LUABIND_POLICY_DECL(z,n,text) typedef typename find_conversion_policy<n + 1, Policies>::type BOOST_PP_CAT(p,n);
337 #define LUABIND_ARITY(z,n,text) + BOOST_PP_CAT(p,n)::has_arg
339 template<class R
BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A
), class Policies
>
340 overload_rep(R(*f
)(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), A
)), Policies
*)
341 : fun(reinterpret_cast<void(*)()>(f
))
342 , m_num_args(BOOST_PP_ITERATION())
344 BOOST_PP_REPEAT(BOOST_PP_ITERATION(), LUABIND_INIT_PARAM
, _
)
345 BOOST_PP_REPEAT(BOOST_PP_ITERATION(), LUABIND_POLICY_DECL
, _
)
347 m_arity
= 0 BOOST_PP_REPEAT(BOOST_PP_ITERATION(), LUABIND_ARITY
, _
);
350 #undef LUABIND_INIT_PARAM
351 #undef LUABIND_POLICY_DECL
354 #elif BOOST_PP_ITERATION_FLAGS() == 2
356 template<class Policies
BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A
)>
357 static int call(T(*f
)(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), A
)), lua_State
* L
, const Policies
*)
359 /* typedef typename get_policy<0, Policies>::type ret_policy;
360 typedef typename ret_policy::head return_value_converter_intermediate;
361 typedef typename return_value_converter_intermediate::template generate_converter<T, cpp_to_lua>::type ret_conv;*/
363 int nargs
= lua_gettop(L
);
365 // typedef typename get_policy_list<0, Policies>::type policy_list_ret;
366 // typedef typename find_converter_policy<policy_list_ret>::type converter_policy_ret;
367 typedef typename find_conversion_policy
<0, Policies
>::type converter_policy_ret
;
368 typename
converter_policy_ret::template generate_converter
<T
, cpp_to_lua
>::type converter_ret
;
370 BOOST_PP_REPEAT(BOOST_PP_ITERATION(), LUABIND_DECL
, _
)
371 converter_ret
.apply(L
, f
373 BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_PARAMS
, _
)
375 BOOST_PP_REPEAT(BOOST_PP_ITERATION(), LUABIND_POSTCALL
, _
)
377 int nret
= lua_gettop(L
) - nargs
;
379 const int indices
[] =
382 nargs
+ nret
/* result*/
383 BOOST_PP_ENUM_TRAILING(BOOST_PP_ITERATION(), LUABIND_INDEX_MAP
, _
)
386 policy_list_postcall
<Policies
>::apply(L
, indices
);
393 #elif BOOST_PP_ITERATION_FLAGS() == 3
395 template<class Policies
BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A
)>
396 static int call(void(*f
)(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), A
)), lua_State
* L
, const Policies
*)
398 int nargs
= lua_gettop(L
);
400 BOOST_PP_REPEAT(BOOST_PP_ITERATION(), LUABIND_DECL
, _
)
403 BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_PARAMS
, _
)
405 BOOST_PP_REPEAT(BOOST_PP_ITERATION(), LUABIND_POSTCALL
, _
)
407 int nret
= lua_gettop(L
) - nargs
;
409 const int indices
[] =
412 nargs
+ nret
/* result*/
413 BOOST_PP_ENUM_TRAILING(BOOST_PP_ITERATION(), LUABIND_INDEX_MAP
, _
)
416 policy_list_postcall
<Policies
>::apply(L
, indices
);
422 #elif BOOST_PP_ITERATION_FLAGS() == 4
424 template<class Policies
, class R
BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A
)>
425 int call(R(*f
)(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), A
)), lua_State
* L
, const Policies
* policies
)
427 return free_functions::returns
<R
>::call(f
, L
, policies
);
430 #elif BOOST_PP_ITERATION_FLAGS() == 5
432 template<class Policies
, class R
BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A
)>
433 static int match(R(*)(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), A
)), lua_State
* L
, const Policies
* policies
)
435 //if (lua_gettop(L) != BOOST_PP_ITERATION()) return -1;
436 typedef constructor
<BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), A
)> ParameterTypes
;
437 return match_params(L
, 1, static_cast<ParameterTypes
*>(0), policies
);