added finalizers
[luabind.git] / luabind / function.hpp
blobb52ffb6c10f9886fad518bdce934eb8cb4e2d5c8
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>
43 #include <luabind/scope.hpp>
45 namespace luabind
47 namespace detail
50 namespace free_functions
53 struct overload_rep: public overload_rep_base
56 #define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, <luabind/function.hpp>, 1))
57 #include BOOST_PP_ITERATE()
59 inline bool operator==(const overload_rep& o) const
61 if (o.m_arity != m_arity) return false;
62 if (o.m_num_args != m_num_args) return false;
63 for (int i = 0; i < m_num_args; ++i)
64 if (!(LUABIND_TYPE_INFO_EQUAL(m_params[i], o.m_params[i]))) return false;
65 return true;
68 typedef int(*call_ptr)(lua_State*, void(*)());
70 inline void set_fun(call_ptr f) { call_fun = f; }
71 inline int call(lua_State* L, void(*f)()) const { return call_fun(L, f); }
73 // this is the actual function pointer to be called when this overload is invoked
74 void (*fun)();
76 private:
78 int m_num_args;
79 call_ptr call_fun;
81 // the number of parameters this overload takes
82 // these are used to detect when a function by a derived class.
83 // int m_arity;
84 // the types of the parameter it takes
85 LUABIND_TYPE_INFO m_params[LUABIND_MAX_ARITY];
91 struct function_rep
93 void add_overload(const free_functions::overload_rep& o)
95 std::vector<free_functions::overload_rep>::iterator i = std::find(m_overloads.begin(), m_overloads.end(), o);
97 // if the overload already exists, overwrite the existing function
98 if (i != m_overloads.end())
100 *i = o;
102 else
104 m_overloads.push_back(o);
108 const std::vector<overload_rep>& overloads() const throw() { return m_overloads; }
110 #ifdef LUABIND_DONT_COPY_STRINGS
111 const char* name;
112 #else
113 std::string name;
114 #endif
116 private:
117 // this have to be write protected, since each time an overload is
118 // added it has to be checked for existence. add_overload() should
119 // be used.
120 std::vector<free_functions::overload_rep> m_overloads;
125 // returns generates functions that calls function pointers
127 #define LUABIND_DECL(z, n, text) typedef typename detail::get_policy<n+1,Policies>::type BOOST_PP_CAT(a##n,_policy); \
128 typedef typename BOOST_PP_CAT(a##n,_policy)::head BOOST_PP_CAT(a##n,_param_converter_intermediate); \
129 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);
131 #define LUABIND_PARAMS(z,n,text) BOOST_PP_CAT(p##n,_conv)::apply(L, LUABIND_DECORATE_TYPE(A##n), n + 1)
134 #define LUABIND_DECL(z, n, text) typedef typename find_conversion_policy<n + 1, Policies>::type BOOST_PP_CAT(converter_policy,n); \
135 typename BOOST_PP_CAT(converter_policy,n)::template generate_converter<A##n, lua_to_cpp>::type BOOST_PP_CAT(c,n);
137 #define LUABIND_ADD_INDEX(z,n,text) + BOOST_PP_CAT(converter_policy,n)::has_arg
138 #define LUABIND_INDEX_MAP(z,n,text) 1 BOOST_PP_REPEAT(n, LUABIND_ADD_INDEX, _)
139 #define LUABIND_PARAMS(z,n,text) BOOST_PP_CAT(c,n).apply(L, LUABIND_DECORATE_TYPE(A##n), LUABIND_INDEX_MAP(_,n,_))
140 #define LUABIND_POSTCALL(z,n,text) BOOST_PP_CAT(c,n).converter_postcall(L, LUABIND_DECORATE_TYPE(A##n), LUABIND_INDEX_MAP(_,n,_));
142 template<class T>
143 struct returns
145 #define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, <luabind/function.hpp>, 2))
146 #include BOOST_PP_ITERATE()
149 template<>
150 struct returns<void>
152 #define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, <luabind/function.hpp>, 3))
153 #include BOOST_PP_ITERATE()
156 #define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, <luabind/function.hpp>, 4))
157 #include BOOST_PP_ITERATE()
160 #undef LUABIND_PARAMS
161 #undef LUABIND_DECL
162 #undef LUABIND_POSTCALL
163 #undef LUABIND_ADD_INDEX
164 #undef LUABIND_INDEX_MAP
167 #define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, <luabind/function.hpp>, 5))
168 #include BOOST_PP_ITERATE()
173 struct function_registry
175 std::map<const char*, free_functions::function_rep, ltstr> m_functions;
176 #ifndef LUABIND_DONT_COPY_STRINGS
177 std::vector<char*> m_strings;
179 ~function_registry()
181 for (std::vector<char*>::iterator i = m_strings.begin(); i != m_strings.end(); ++i)
182 delete[] *i;
184 #endif
187 template<class F, class Policies>
188 struct function_callback_s
190 static inline int apply(lua_State* L, void(*fun)())
192 return free_functions::call(reinterpret_cast<F>(fun), L, static_cast<const Policies*>(0));
196 template<class F, class Policies>
197 struct match_function_callback_s
199 static inline int apply(lua_State* L)
201 F fptr = 0;
202 return free_functions::match(fptr, L, static_cast<Policies*>(0));
205 static int callback(lua_State* L)
207 F fptr = 0;
208 return free_functions::match(fptr, L, static_cast<Policies*>(0));
212 #ifdef LUABIND_NO_HEADERS_ONLY
213 int function_dispatcher(lua_State* L);
214 #else
215 // inline int function_dispatcher(lua_State* L)
217 function_rep* rep = static_cast<function_rep*>(lua_touserdata(L, lua_upvalueindex(1)));
219 bool ambiguous = false;
220 int min_match = std::numeric_limits<int>::max();
221 int match_index = -1;
222 bool ret;
224 #ifdef LUABIND_NO_ERROR_CHECKING
226 if (rep->overloads().size() == 1)
228 match_index = 0;
230 else
233 #endif
234 int num_params = lua_gettop(L);
235 ret = find_best_match(L, &rep->overloads().front(), rep->overloads().size(), sizeof(free_functions::overload_rep), ambiguous, min_match, match_index, num_params);
237 #ifdef LUABIND_NO_ERROR_CHECKING
240 #else
242 if (!ret)
244 // this bock is needed to make sure the std::string is destructed
246 std::string msg = "no match for function call '";
247 msg += rep->name;
248 msg += "' with the parameters (";
249 msg += stack_content_by_name(L, 1);
250 msg += ")\ncandidates are:\n";
252 msg += get_overload_signatures(L, rep->overloads().begin(), rep->overloads().end(), rep->name);
254 lua_pushstring(L, msg.c_str());
256 lua_error(L);
259 if (ambiguous)
261 // this bock is needed to make sure the std::string is destructed
263 std::string msg = "call of overloaded function '";
264 msg += rep->name;
265 msg += "(";
266 msg += stack_content_by_name(L, 1);
267 msg += ") is ambiguous\nnone of the overloads have a best conversion:";
269 std::vector<const overload_rep_base*> candidates;
270 find_exact_match(L, &rep->overloads().front(), rep->overloads().size(), sizeof(free_functions::overload_rep), min_match, num_params, candidates);
272 msg += get_overload_signatures_candidates(L, candidates.begin(), candidates.end(), rep->name);
274 lua_pushstring(L, msg.c_str());
276 lua_error(L);
278 #endif
279 const overload_rep& ov_rep = rep->overloads()[match_index];
280 return ov_rep.call(L, ov_rep.fun);
282 #endif
286 template<class F, class Policies>
287 void function(lua_State* L, const char* name, F f, const Policies&)
289 detail::free_functions::function_registry* registry = 0;
290 lua_pushstring(L, "__lua_free_functions");
291 lua_gettable(L, LUA_REGISTRYINDEX);
293 registry = static_cast<detail::free_functions::function_registry*>(lua_touserdata(L, -1));
294 lua_pop(L, 1);
296 // if you hit this assert you have not called luabind::open() for
297 // this lua_State. See the documentation for more information.
298 assert(registry != 0);
300 #ifdef LUABIND_DONT_COPY_STRINGS
301 detail::free_functions::function_rep& rep = registry->m_functions[name];
302 #else
303 registry->m_strings.push_back(detail::dup_string(name));
304 detail::free_functions::function_rep& rep = registry->m_functions[registry->m_strings.back()];
305 #endif
307 detail::free_functions::overload_rep o(f, static_cast<Policies*>(0));
309 o.set_match_fun(&detail::free_functions::match_function_callback_s<F, Policies>::apply);
310 o.set_fun(&detail::free_functions::function_callback_s<F, Policies>::apply);
312 #ifndef LUABIND_NO_ERROR_CHECKING
313 o.set_sig_fun(&detail::get_free_function_signature<F>::apply);
314 #endif
316 rep.add_overload(o);
317 rep.name = name;
319 lua_pushstring(L, name);
320 lua_pushlightuserdata(L, &rep);
321 lua_pushcclosure(L, detail::free_functions::function_dispatcher, 1);
322 lua_settable(L, LUA_GLOBALSINDEX);
325 template<class F>
326 void function(lua_State* L, const char* name, F f)
328 luabind::function(L, name, f, detail::null_type());
331 namespace detail
333 template<class F, class Policies>
334 struct function_commiter : detail::scoped_object
336 function_commiter(const char* n, F f, const Policies& p)
337 : name(n)
338 , fun(f)
339 , policies(p)
342 virtual detail::scoped_object* clone() const
344 return new function_commiter(*this);
347 virtual void commit(lua_State* L) const
349 detail::free_functions::function_registry* registry = 0;
350 lua_pushstring(L, "__lua_free_functions");
351 lua_gettable(L, LUA_REGISTRYINDEX);
353 registry = static_cast<detail::free_functions::function_registry*>(lua_touserdata(L, -1));
354 lua_pop(L, 1);
356 // if you hit this assert you have not called luabind::open() for
357 // this lua_State. See the documentation for more information.
358 assert(registry != 0);
360 #ifdef LUABIND_DONT_COPY_STRINGS
361 detail::free_functions::function_rep& rep = registry->m_functions[name.c_str()];
362 #else
363 registry->m_strings.push_back(detail::dup_string(name.c_str()));
364 detail::free_functions::function_rep& rep = registry->m_functions[registry->m_strings.back()];
365 #endif
367 detail::free_functions::overload_rep o(fun, static_cast<Policies*>(0));
369 o.set_match_fun(&detail::free_functions::match_function_callback_s<F, Policies>::apply);
370 o.set_fun(&detail::free_functions::function_callback_s<F, Policies>::apply);
372 #ifndef LUABIND_NO_ERROR_CHECKING
373 o.set_sig_fun(&detail::get_free_function_signature<F>::apply);
374 #endif
376 rep.add_overload(o);
377 rep.name = name.c_str();
379 detail::getref(L, scope_stack::top(L));
380 lua_pushstring(L, name.c_str());
381 lua_pushlightuserdata(L, &rep);
382 lua_pushcclosure(L, free_functions::function_dispatcher, 1);
383 lua_settable(L, -3);
386 std::string name;
387 F fun;
388 Policies policies;
392 template<class F, class Policies>
393 detail::function_commiter<F,Policies>
394 def(const char* name, F f, const Policies& policies)
396 return detail::function_commiter<F,Policies>(name, f, policies);
399 template<class F>
400 detail::function_commiter<F, detail::null_type>
401 def(const char* name, F f)
403 return detail::function_commiter<F,detail::null_type>(name, f, detail::null_type());
406 } // namespace luabind
409 #endif // LUABIND_FUNCTION_HPP_INCLUDED
411 #elif BOOST_PP_ITERATION_FLAGS() == 1
413 // overloaded template funtion that initializes the parameter list
414 // called m_params and the m_arity member.
416 #define LUABIND_INIT_PARAM(z, n, _) m_params[n] = LUABIND_TYPEID(A##n);
417 #define LUABIND_POLICY_DECL(z,n,text) typedef typename find_conversion_policy<n + 1, Policies>::type BOOST_PP_CAT(p,n);
418 #define LUABIND_ARITY(z,n,text) + BOOST_PP_CAT(p,n)::has_arg
420 template<class R BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A), class Policies>
421 overload_rep(R(*f)(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), A)), Policies*)
422 : fun(reinterpret_cast<void(*)()>(f))
423 , m_num_args(BOOST_PP_ITERATION())
425 BOOST_PP_REPEAT(BOOST_PP_ITERATION(), LUABIND_INIT_PARAM, _)
426 BOOST_PP_REPEAT(BOOST_PP_ITERATION(), LUABIND_POLICY_DECL, _)
428 m_arity = 0 BOOST_PP_REPEAT(BOOST_PP_ITERATION(), LUABIND_ARITY, _);
431 #undef LUABIND_INIT_PARAM
432 #undef LUABIND_POLICY_DECL
433 #undef LUABIND_ARITY
435 #elif BOOST_PP_ITERATION_FLAGS() == 2
437 template<class Policies BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A)>
438 static int call(T(*f)(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), A)), lua_State* L, const Policies*)
440 /* typedef typename get_policy<0, Policies>::type ret_policy;
441 typedef typename ret_policy::head return_value_converter_intermediate;
442 typedef typename return_value_converter_intermediate::template generate_converter<T, cpp_to_lua>::type ret_conv;*/
444 int nargs = lua_gettop(L);
446 // typedef typename get_policy_list<0, Policies>::type policy_list_ret;
447 // typedef typename find_converter_policy<policy_list_ret>::type converter_policy_ret;
448 typedef typename find_conversion_policy<0, Policies>::type converter_policy_ret;
449 typename converter_policy_ret::template generate_converter<T, cpp_to_lua>::type converter_ret;
451 BOOST_PP_REPEAT(BOOST_PP_ITERATION(), LUABIND_DECL, _)
452 converter_ret.apply(L, f
454 BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_PARAMS, _)
456 BOOST_PP_REPEAT(BOOST_PP_ITERATION(), LUABIND_POSTCALL, _)
458 int nret = lua_gettop(L) - nargs;
460 const int indices[] =
462 -1 /* self */,
463 nargs + nret /* result*/
464 BOOST_PP_ENUM_TRAILING(BOOST_PP_ITERATION(), LUABIND_INDEX_MAP, _)
467 policy_list_postcall<Policies>::apply(L, indices);
469 return nret;
474 #elif BOOST_PP_ITERATION_FLAGS() == 3
476 template<class Policies BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A)>
477 static int call(void(*f)(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), A)), lua_State* L, const Policies*)
479 int nargs = lua_gettop(L);
481 BOOST_PP_REPEAT(BOOST_PP_ITERATION(), LUABIND_DECL, _)
484 BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_PARAMS, _)
486 BOOST_PP_REPEAT(BOOST_PP_ITERATION(), LUABIND_POSTCALL, _)
488 int nret = lua_gettop(L) - nargs;
490 const int indices[] =
492 -1 /* self */,
493 nargs + nret /* result*/
494 BOOST_PP_ENUM_TRAILING(BOOST_PP_ITERATION(), LUABIND_INDEX_MAP, _)
497 policy_list_postcall<Policies>::apply(L, indices);
499 return nret;
503 #elif BOOST_PP_ITERATION_FLAGS() == 4
505 template<class Policies, class R BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A)>
506 int call(R(*f)(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), A)), lua_State* L, const Policies* policies)
508 return free_functions::returns<R>::call(f, L, policies);
511 #elif BOOST_PP_ITERATION_FLAGS() == 5
513 template<class Policies, class R BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A)>
514 static int match(R(*)(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), A)), lua_State* L, const Policies* policies)
516 //if (lua_gettop(L) != BOOST_PP_ITERATION()) return -1;
517 typedef constructor<BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), A)> ParameterTypes;
518 return match_params(L, 1, static_cast<ParameterTypes*>(0), policies);
523 #endif