Added __stdcall fix missing from previous commit.
[luabind.git] / luabind / function.hpp
blob49b9353aa10ea8b21261d085d85d5dc18ddf245f
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>
38 #include <boost/mpl/apply_wrap.hpp>
40 #include <luabind/detail/signature_match.hpp>
41 #include <luabind/detail/call_function.hpp>
42 #include <luabind/detail/get_overload_signature.hpp>
43 #include <luabind/detail/overload_rep_base.hpp>
45 #include <luabind/scope.hpp>
47 namespace luabind
49 namespace detail
52 namespace mpl = boost::mpl;
54 namespace free_functions
57 struct overload_rep: public overload_rep_base
60 #define LUABIND_CC
61 #define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, <luabind/function.hpp>, 1))
62 #include BOOST_PP_ITERATE()
63 #undef LUABIND_CC
65 #ifdef BOOST_MSVC
66 # define LUABIND_CC __stdcall
67 # define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, <luabind/function.hpp>, 1))
68 # include BOOST_PP_ITERATE()
69 # undef LUABIND_CC
70 #endif
72 inline bool operator==(const overload_rep& o) const
74 if (o.m_arity != m_arity) return false;
75 if (o.m_params_.size() != m_params_.size()) return false;
76 for (int i = 0; i < (int)m_params_.size(); ++i)
77 if (!(LUABIND_TYPE_INFO_EQUAL(m_params_[i], o.m_params_[i]))) return false;
78 return true;
81 typedef int(*call_ptr)(lua_State*, void(*)());
83 inline void set_fun(call_ptr f) { call_fun = f; }
84 inline int call(lua_State* L, void(*f)()) const { return call_fun(L, f); }
86 // this is the actual function pointer to be called when this overload is invoked
87 void (*fun)();
89 //TODO: private:
91 call_ptr call_fun;
93 // the types of the parameter it takes
94 std::vector<LUABIND_TYPE_INFO> m_params_;
96 char end;
99 struct LUABIND_API function_rep
101 function_rep(const char* name): m_name(name) {}
102 void add_overload(const free_functions::overload_rep& o);
104 const std::vector<overload_rep>& overloads() const throw() { return m_overloads; }
106 const char* name() const { return m_name; }
108 private:
109 const char* m_name;
111 // this have to be write protected, since each time an overload is
112 // added it has to be checked for existence. add_overload() should
113 // be used.
114 std::vector<free_functions::overload_rep> m_overloads;
119 // returns generates functions that calls function pointers
121 #define LUABIND_DECL(z, n, text) typedef typename find_conversion_policy<n + 1, Policies>::type BOOST_PP_CAT(converter_policy,n); \
122 typename mpl::apply_wrap2< \
123 BOOST_PP_CAT(converter_policy,n), BOOST_PP_CAT(A,n), lua_to_cpp \
124 >::type BOOST_PP_CAT(c,n);
126 #define LUABIND_ADD_INDEX(z,n,text) + BOOST_PP_CAT(converter_policy,n)::has_arg
127 #define LUABIND_INDEX_MAP(z,n,text) 1 BOOST_PP_REPEAT(n, LUABIND_ADD_INDEX, _)
128 #define LUABIND_PARAMS(z,n,text) BOOST_PP_CAT(c,n).apply(L, LUABIND_DECORATE_TYPE(A##n), LUABIND_INDEX_MAP(_,n,_))
129 #define LUABIND_POSTCALL(z,n,text) BOOST_PP_CAT(c,n).converter_postcall(L, LUABIND_DECORATE_TYPE(A##n), LUABIND_INDEX_MAP(_,n,_));
131 template<class Policies>
132 struct maybe_yield
134 static inline int apply(lua_State* L, int nret)
136 return ret(L, nret, boost::mpl::bool_<has_yield<Policies>::value>());
139 static inline int ret(lua_State* L, int nret, boost::mpl::bool_<true>)
141 return lua_yield(L, nret);
144 static inline int ret(lua_State*, int nret, boost::mpl::bool_<false>)
146 return nret;
151 template<class T>
152 struct returns
154 #define LUABIND_CC
155 #define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, <luabind/function.hpp>, 2))
156 #include BOOST_PP_ITERATE()
157 #undef LUABIND_CC
159 #ifdef BOOST_MSVC
160 # define LUABIND_CC __stdcall
161 # define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, <luabind/function.hpp>, 2))
162 # include BOOST_PP_ITERATE()
163 # undef LUABIND_CC
164 #endif
167 template<>
168 struct returns<void>
170 #define LUABIND_CC
171 #define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, <luabind/function.hpp>, 3))
172 #include BOOST_PP_ITERATE()
173 #undef LUABIND_CC
175 #ifdef BOOST_MSVC
176 # define LUABIND_CC __stdcall
177 # define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, <luabind/function.hpp>, 3))
178 # include BOOST_PP_ITERATE()
179 # undef LUABIND_CC
180 #endif
183 #define LUABIND_CC
184 #define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, <luabind/function.hpp>, 4))
185 #include BOOST_PP_ITERATE()
186 #undef LUABIND_CC
188 #ifdef BOOST_MSVC
189 # define LUABIND_CC __stdcall
190 # define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, <luabind/function.hpp>, 4))
191 # include BOOST_PP_ITERATE()
192 # undef LUABIND_CC
193 #endif
195 #undef LUABIND_PARAMS
196 #undef LUABIND_DECL
197 #undef LUABIND_POSTCALL
198 #undef LUABIND_ADD_INDEX
199 #undef LUABIND_INDEX_MAP
201 #define LUABIND_CC
202 #define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, <luabind/function.hpp>, 5))
203 #include BOOST_PP_ITERATE()
204 #undef LUABIND_CC
206 #ifdef BOOST_MSVC
207 # define LUABIND_CC __stdcall
208 # define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, <luabind/function.hpp>, 5))
209 # include BOOST_PP_ITERATE()
210 # undef LUABIND_CC
211 #endif
213 template<class F, class Policies>
214 struct function_callback_s
216 static inline int apply(lua_State* L, void(*fun)())
218 return free_functions::call(reinterpret_cast<F>(fun), L, static_cast<const Policies*>(0));
222 template<class F, class Policies>
223 struct match_function_callback_s
225 static inline int apply(lua_State* L)
227 F fptr = 0;
228 return free_functions::match(fptr, L, static_cast<Policies*>(0));
231 static int callback(lua_State* L)
233 F fptr = 0;
234 return free_functions::match(fptr, L, static_cast<Policies*>(0));
238 LUABIND_API int function_dispatcher(lua_State* L);
242 // deprecated
243 template<class F, class Policies>
244 void function(lua_State* L, const char* name, F f, const Policies& p)
246 module(L) [ def(name, f, p) ];
249 // deprecated
250 template<class F>
251 void function(lua_State* L, const char* name, F f)
253 luabind::function(L, name, f, detail::null_type());
256 namespace detail
258 template<class F, class Policies>
259 struct function_commiter : detail::registration
261 function_commiter(const char* n, F f, const Policies& p)
262 : m_name(n)
263 , fun(f)
264 , policies(p)
267 virtual void register_(lua_State* L) const
269 detail::free_functions::overload_rep o(fun, static_cast<Policies*>(0));
271 o.set_match_fun(&detail::free_functions::match_function_callback_s<F, Policies>::apply);
272 o.set_fun(&detail::free_functions::function_callback_s<F, Policies>::apply);
274 #ifndef LUABIND_NO_ERROR_CHECKING
275 o.set_sig_fun(&detail::get_free_function_signature<F>::apply);
276 #endif
278 lua_pushstring(L, m_name);
279 lua_gettable(L, -2);
281 detail::free_functions::function_rep* rep = 0;
282 if (lua_iscfunction(L, -1))
284 if (lua_getupvalue(L, -1, 2) != 0)
286 // check the magic number that identifies luabind's functions
287 if (lua_touserdata(L, -1) == (void*)0x1337)
289 if (lua_getupvalue(L, -2, 1) != 0)
291 rep = static_cast<detail::free_functions::function_rep*>(lua_touserdata(L, -1));
292 lua_pop(L, 1);
295 lua_pop(L, 1);
298 lua_pop(L, 1);
300 if (rep == 0)
302 lua_pushstring(L, m_name);
303 // create a new function_rep
304 rep = static_cast<detail::free_functions::function_rep*>(lua_newuserdata(L, sizeof(detail::free_functions::function_rep)));
305 new(rep) detail::free_functions::function_rep(m_name);
307 // STORE IN REGISTRY
308 lua_pushvalue(L, -1);
309 detail::ref(L);
311 detail::class_registry* r = detail::class_registry::get_registry(L);
312 assert(r && "you must call luabind::open() prior to any function registrations");
313 detail::getref(L, r->lua_function());
314 int ret = lua_setmetatable(L, -2);
315 (void)ret;
316 assert(ret != 0);
318 // this is just a magic number to identify functions that luabind created
319 lua_pushlightuserdata(L, (void*)0x1337);
321 lua_pushcclosure(L, &free_functions::function_dispatcher, 2);
322 lua_settable(L, -3);
325 rep->add_overload(o);
328 char const* m_name;
329 F fun;
330 Policies policies;
334 template<class F, class Policies>
335 scope def(const char* name, F f, const Policies& policies)
337 return scope(std::auto_ptr<detail::registration>(
338 new detail::function_commiter<F,Policies>(name, f, policies)));
341 template<class F>
342 scope def(const char* name, F f)
344 return scope(std::auto_ptr<detail::registration>(
345 new detail::function_commiter<F,detail::null_type>(
346 name, f, detail::null_type())));
349 } // namespace luabind
352 #endif // LUABIND_FUNCTION_HPP_INCLUDED
354 #elif BOOST_PP_ITERATION_FLAGS() == 1
356 // overloaded template funtion that initializes the parameter list
357 // called m_params and the m_arity member.
359 #define LUABIND_INIT_PARAM(z, n, _) m_params_.push_back(LUABIND_TYPEID(A##n));
360 #define LUABIND_POLICY_DECL(z,n,text) typedef typename find_conversion_policy<n + 1, Policies>::type BOOST_PP_CAT(p,n);
361 #define LUABIND_ARITY(z,n,text) + BOOST_PP_CAT(p,n)::has_arg
363 template<class R BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A), class Policies>
364 overload_rep(R(LUABIND_CC *f)(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), A)), Policies*)
365 : fun(reinterpret_cast<void(*)()>(f))
367 m_params_.reserve(BOOST_PP_ITERATION());
368 BOOST_PP_REPEAT(BOOST_PP_ITERATION(), LUABIND_INIT_PARAM, _)
369 BOOST_PP_REPEAT(BOOST_PP_ITERATION(), LUABIND_POLICY_DECL, _)
371 m_arity = 0 BOOST_PP_REPEAT(BOOST_PP_ITERATION(), LUABIND_ARITY, _);
374 #undef LUABIND_INIT_PARAM
375 #undef LUABIND_POLICY_DECL
376 #undef LUABIND_ARITY
378 #elif BOOST_PP_ITERATION_FLAGS() == 2
380 template<class Policies BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A)>
381 static int call(T(LUABIND_CC *f)(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), A)), lua_State* L, const Policies*)
383 int nargs = lua_gettop(L);
385 typedef typename find_conversion_policy<0, Policies>::type converter_policy_ret;
386 typename mpl::apply_wrap2<converter_policy_ret,T,cpp_to_lua>::type converter_ret;
388 BOOST_PP_REPEAT(BOOST_PP_ITERATION(), LUABIND_DECL, _)
389 converter_ret.apply(L, f
391 BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_PARAMS, _)
393 BOOST_PP_REPEAT(BOOST_PP_ITERATION(), LUABIND_POSTCALL, _)
395 int nret = lua_gettop(L) - nargs;
397 const int indices[] =
399 -1 /* self */,
400 nargs + nret /* result*/
401 BOOST_PP_ENUM_TRAILING(BOOST_PP_ITERATION(), LUABIND_INDEX_MAP, _)
404 policy_list_postcall<Policies>::apply(L, indices);
406 return maybe_yield<Policies>::apply(L, nret);
411 #elif BOOST_PP_ITERATION_FLAGS() == 3
413 template<class Policies BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A)>
414 static int call(void(LUABIND_CC *f)(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), A)), lua_State* L, const Policies*)
416 int nargs = lua_gettop(L);
418 BOOST_PP_REPEAT(BOOST_PP_ITERATION(), LUABIND_DECL, _)
421 BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_PARAMS, _)
423 BOOST_PP_REPEAT(BOOST_PP_ITERATION(), LUABIND_POSTCALL, _)
425 int nret = lua_gettop(L) - nargs;
427 const int indices[] =
429 -1 /* self */,
430 nargs + nret /* result*/
431 BOOST_PP_ENUM_TRAILING(BOOST_PP_ITERATION(), LUABIND_INDEX_MAP, _)
434 policy_list_postcall<Policies>::apply(L, indices);
436 return maybe_yield<Policies>::apply(L, nret);
440 #elif BOOST_PP_ITERATION_FLAGS() == 4
442 template<class Policies, class R BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A)>
443 int call(R(LUABIND_CC *f)(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), A)), lua_State* L, const Policies* policies)
445 return free_functions::returns<R>::call(f, L, policies);
448 #elif BOOST_PP_ITERATION_FLAGS() == 5
450 template<class Policies, class R BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A)>
451 static int match(R(LUABIND_CC *)(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), A)), lua_State* L, const Policies* policies)
453 //if (lua_gettop(L) != BOOST_PP_ITERATION()) return -1;
454 typedef constructor<BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), A)> ParameterTypes;
455 return match_params(L, 1, static_cast<ParameterTypes*>(0), policies);
460 #endif