*** empty log message ***
[luabind.git] / luabind / function.hpp
blob26b218b175692c6a5ccbc8d76f8e865f1df43333
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>
46 namespace luabind
48 namespace detail
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_num_args != m_num_args) return false;
64 for (int i = 0; i < m_num_args; ++i)
65 if (!(LUABIND_TYPE_INFO_EQUAL(m_params[i], o.m_params[i]))) return false;
66 return true;
69 typedef int(*call_ptr)(lua_State*, void(*)(), void*);
71 inline void set_fun(call_ptr f) { call_fun = f; }
72 inline int call(lua_State* L, void(*f)(), void* storage) const { return call_fun(L, f, storage); }
74 // this is the actual function pointer to be called when this overload is invoked
75 void (*fun)();
77 private:
79 int m_num_args;
80 call_ptr call_fun;
82 // the number of parameters this overload takes
83 // these are used to detect when a function by a derived class.
84 // int m_arity;
85 // the types of the parameter it takes
86 LUABIND_TYPE_INFO m_params[LUABIND_MAX_ARITY];
92 struct function_rep
94 #ifdef LUABIND_DONT_COPY_STRINGS
95 function_rep(const char* name): m_name(name) {}
96 #else
97 function_rep(const std::string& name): m_name(name) {}
98 #endif
99 void add_overload(const free_functions::overload_rep& o)
101 std::vector<free_functions::overload_rep>::iterator i = std::find(m_overloads.begin(), m_overloads.end(), o);
103 // if the overload already exists, overwrite the existing function
104 if (i != m_overloads.end())
106 *i = o;
108 else
110 m_overloads.push_back(o);
114 const std::vector<overload_rep>& overloads() const throw() { return m_overloads; }
116 #ifdef LUABIND_DONT_COPY_STRINGS
117 const char* name() const { return m_name; }
118 #else
119 const char* name() const { return m_name.c_str(); }
120 #endif
122 private:
124 #ifdef LUABIND_DONT_COPY_STRINGS
125 const char* m_name;
126 #else
127 std::string m_name;
128 #endif
130 // this have to be write protected, since each time an overload is
131 // added it has to be checked for existence. add_overload() should
132 // be used.
133 std::vector<free_functions::overload_rep> m_overloads;
138 // returns generates functions that calls function pointers
140 #define LUABIND_DECL(z, n, text) typedef typename find_conversion_policy<n + 1, Policies>::type BOOST_PP_CAT(converter_policy,n); \
141 typename BOOST_PP_CAT(converter_policy,n)::template generate_converter<A##n, lua_to_cpp>::type BOOST_PP_CAT(c,n);
143 #define LUABIND_ADD_INDEX(z,n,text) + BOOST_PP_CAT(converter_policy,n)::has_arg
144 #define LUABIND_INDEX_MAP(z,n,text) 1 BOOST_PP_REPEAT(n, LUABIND_ADD_INDEX, _)
145 #define LUABIND_PARAMS(z,n,text) BOOST_PP_CAT(c,n).apply(L, LUABIND_DECORATE_TYPE(A##n), LUABIND_INDEX_MAP(_,n,_))
146 #define LUABIND_POSTCALL(z,n,text) BOOST_PP_CAT(c,n).converter_postcall(L, LUABIND_DECORATE_TYPE(A##n), LUABIND_INDEX_MAP(_,n,_));
148 template<class Policies>
149 struct maybe_yield
151 static inline int apply(lua_State* L, int nret)
153 return ret(L, nret, boost::mpl::bool_<has_yield<Policies>::value>());
156 static inline int ret(lua_State* L, int nret, boost::mpl::bool_<true>)
158 return lua_yield(L, nret);
161 static inline int ret(lua_State*, int nret, boost::mpl::bool_<false>)
163 return nret;
168 template<class T>
169 struct returns
171 #define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, <luabind/function.hpp>, 2))
172 #include BOOST_PP_ITERATE()
175 template<>
176 struct returns<void>
178 #define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, <luabind/function.hpp>, 3))
179 #include BOOST_PP_ITERATE()
182 #define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, <luabind/function.hpp>, 4))
183 #include BOOST_PP_ITERATE()
186 #undef LUABIND_PARAMS
187 #undef LUABIND_DECL
188 #undef LUABIND_POSTCALL
189 #undef LUABIND_ADD_INDEX
190 #undef LUABIND_INDEX_MAP
193 #define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, <luabind/function.hpp>, 5))
194 #include BOOST_PP_ITERATE()
197 template<class F, class Policies>
198 struct function_callback_s
200 static inline int apply(lua_State* L, void(*fun)(), void* storage)
202 return free_functions::call(reinterpret_cast<F>(fun), L, static_cast<const Policies*>(0), storage);
206 template<class F, class Policies>
207 struct match_function_callback_s
209 static inline int apply(lua_State* L)
211 F fptr = 0;
212 return free_functions::match(fptr, L, static_cast<Policies*>(0));
215 static int callback(lua_State* L)
217 F fptr = 0;
218 return free_functions::match(fptr, L, static_cast<Policies*>(0));
222 LUABIND_API int function_dispatcher(lua_State* L);
226 // deprecated
227 template<class F, class Policies>
228 void function(lua_State* L, const char* name, F f, const Policies& p)
230 module(L) [ def(name, f, p) ];
233 // deprecated
234 template<class F>
235 void function(lua_State* L, const char* name, F f)
237 luabind::function(L, name, f, detail::null_type());
240 namespace detail
242 template<class F, class Policies>
243 struct function_commiter : detail::registration
245 function_commiter(const char* n, F f, const Policies& p)
246 : m_name(n)
247 , fun(f)
248 , policies(p)
251 virtual void register_(lua_State* L) const
253 detail::free_functions::overload_rep o(fun, static_cast<Policies*>(0));
255 o.set_match_fun(&detail::free_functions::match_function_callback_s<F, Policies>::apply);
256 o.set_fun(&detail::free_functions::function_callback_s<F, Policies>::apply);
258 #ifndef LUABIND_NO_ERROR_CHECKING
259 o.set_sig_fun(&detail::get_free_function_signature<F>::apply);
260 #endif
262 lua_pushstring(L, m_name.c_str());
263 lua_gettable(L, -2);
265 detail::free_functions::function_rep* rep = 0;
266 if (lua_iscfunction(L, -1))
268 if (lua_getupvalue(L, -1, 2) != 0)
270 // check the magic number that identifies luabind's functions
271 if (lua_touserdata(L, -1) == (void*)0x1337)
273 if (lua_getupvalue(L, -2, 1) != 0)
275 rep = static_cast<detail::free_functions::function_rep*>(lua_touserdata(L, -1));
276 lua_pop(L, 1);
279 lua_pop(L, 1);
282 lua_pop(L, 1);
284 if (rep == 0)
286 lua_pushstring(L, m_name.c_str());
287 // create a new function_rep
288 rep = static_cast<detail::free_functions::function_rep*>(lua_newuserdata(L, sizeof(detail::free_functions::function_rep)));
289 new(rep) detail::free_functions::function_rep(m_name.c_str());
291 detail::class_registry* r = detail::class_registry::get_registry(L);
292 assert(r && "you must call luabind::open() prior to any function registrations");
293 detail::getref(L, r->lua_function());
294 int ret = lua_setmetatable(L, -2);
295 assert(ret != 0);
297 // this is just a magic number to identify functions that luabind created
298 lua_pushlightuserdata(L, (void*)0x1337);
300 lua_pushcclosure(L, &free_functions::function_dispatcher, 2);
301 lua_settable(L, -3);
304 rep->add_overload(o);
307 std::string m_name;
308 F fun;
309 Policies policies;
313 template<class F, class Policies>
314 scope def(const char* name, F f, const Policies& policies)
316 return scope(std::auto_ptr<detail::registration>(
317 new detail::function_commiter<F,Policies>(name, f, policies)));
320 template<class F>
321 scope def(const char* name, F f)
323 return scope(std::auto_ptr<detail::registration>(
324 new detail::function_commiter<F,detail::null_type>(
325 name, f, detail::null_type())));
328 } // namespace luabind
331 #endif // LUABIND_FUNCTION_HPP_INCLUDED
333 #elif BOOST_PP_ITERATION_FLAGS() == 1
335 // overloaded template funtion that initializes the parameter list
336 // called m_params and the m_arity member.
338 #define LUABIND_INIT_PARAM(z, n, _) m_params[n] = LUABIND_TYPEID(A##n);
339 #define LUABIND_POLICY_DECL(z,n,text) typedef typename find_conversion_policy<n + 1, Policies>::type BOOST_PP_CAT(p,n);
340 #define LUABIND_ARITY(z,n,text) + BOOST_PP_CAT(p,n)::has_arg
342 template<class R BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A), class Policies>
343 overload_rep(R(*f)(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), A)), Policies*)
344 : fun(reinterpret_cast<void(*)()>(f))
345 , m_num_args(BOOST_PP_ITERATION())
347 BOOST_PP_REPEAT(BOOST_PP_ITERATION(), LUABIND_INIT_PARAM, _)
348 BOOST_PP_REPEAT(BOOST_PP_ITERATION(), LUABIND_POLICY_DECL, _)
350 m_arity = 0 BOOST_PP_REPEAT(BOOST_PP_ITERATION(), LUABIND_ARITY, _);
353 #undef LUABIND_INIT_PARAM
354 #undef LUABIND_POLICY_DECL
355 #undef LUABIND_ARITY
357 #elif BOOST_PP_ITERATION_FLAGS() == 2
359 template<class Policies BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A)>
360 static int call(T(*f)(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), A)), lua_State* L, const Policies*, void* storage)
362 /* typedef typename get_policy<0, Policies>::type ret_policy;
363 typedef typename ret_policy::head return_value_converter_intermediate;
364 typedef typename return_value_converter_intermediate::template generate_converter<T, cpp_to_lua>::type ret_conv;*/
366 int nargs = lua_gettop(L);
368 // typedef typename get_policy_list<0, Policies>::type policy_list_ret;
369 // typedef typename find_converter_policy<policy_list_ret>::type converter_policy_ret;
370 typedef typename find_conversion_policy<0, Policies>::type converter_policy_ret;
371 typename converter_policy_ret::template generate_converter<T, cpp_to_lua>::type converter_ret;
373 BOOST_PP_REPEAT(BOOST_PP_ITERATION(), LUABIND_DECL, _)
374 converter_ret.apply(L, f
376 BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_PARAMS, _)
378 BOOST_PP_REPEAT(BOOST_PP_ITERATION(), LUABIND_POSTCALL, _)
380 int nret = lua_gettop(L) - nargs;
382 const int indices[] =
384 -1 /* self */,
385 nargs + nret /* result*/
386 BOOST_PP_ENUM_TRAILING(BOOST_PP_ITERATION(), LUABIND_INDEX_MAP, _)
389 policy_list_postcall<Policies>::apply(L, indices);
391 return maybe_yield<Policies>::apply(L, nret);
396 #elif BOOST_PP_ITERATION_FLAGS() == 3
398 template<class Policies BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A)>
399 static int call(void(*f)(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), A)), lua_State* L, const Policies*, void* storage)
401 int nargs = lua_gettop(L);
403 BOOST_PP_REPEAT(BOOST_PP_ITERATION(), LUABIND_DECL, _)
406 BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_PARAMS, _)
408 BOOST_PP_REPEAT(BOOST_PP_ITERATION(), LUABIND_POSTCALL, _)
410 int nret = lua_gettop(L) - nargs;
412 const int indices[] =
414 -1 /* self */,
415 nargs + nret /* result*/
416 BOOST_PP_ENUM_TRAILING(BOOST_PP_ITERATION(), LUABIND_INDEX_MAP, _)
419 policy_list_postcall<Policies>::apply(L, indices);
421 return maybe_yield<Policies>::apply(L, nret);
425 #elif BOOST_PP_ITERATION_FLAGS() == 4
427 template<class Policies, class R BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A)>
428 int call(R(*f)(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), A)), lua_State* L, const Policies* policies, void* storage)
430 return free_functions::returns<R>::call(f, L, policies, storage);
433 #elif BOOST_PP_ITERATION_FLAGS() == 5
435 template<class Policies, class R BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A)>
436 static int match(R(*)(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), A)), lua_State* L, const Policies* policies)
438 //if (lua_gettop(L) != BOOST_PP_ITERATION()) return -1;
439 typedef constructor<BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), A)> ParameterTypes;
440 return match_params(L, 1, static_cast<ParameterTypes*>(0), policies);
445 #endif