Initial C++0x support.
[luabind.git] / luabind / wrapper_base.hpp
bloba74416b775c4c84d1b99d3e2da3192fb19e08783
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.
23 #if !BOOST_PP_IS_ITERATING
25 #ifndef LUABIND_WRAPPER_BASE_HPP_INCLUDED
26 #define LUABIND_WRAPPER_BASE_HPP_INCLUDED
28 #include <luabind/config.hpp>
29 #include <luabind/weak_ref.hpp>
30 #include <luabind/detail/ref.hpp>
31 #include <luabind/detail/call_member.hpp>
33 #ifndef LUABIND_CPP0x
34 # include <boost/preprocessor/repetition/enum_trailing_params.hpp>
35 # include <boost/preprocessor/repetition/enum_trailing_binary_params.hpp>
36 #endif
38 #include <stdexcept>
40 namespace luabind
42 namespace detail
44 struct wrap_access;
46 // implements the selection between dynamic dispatch
47 // or default implementation calls from within a virtual
48 // function wrapper. The input is the self reference on
49 // the top of the stack. Output is the function to call
50 // on the top of the stack (the input self reference will
51 // be popped)
52 LUABIND_API void do_call_member_selection(lua_State* L, char const* name);
55 struct wrapped_self_t: weak_ref
57 detail::lua_reference m_strong_ref;
60 struct wrap_base
62 friend struct detail::wrap_access;
63 wrap_base() {}
65 # ifdef LUABIND_CPP0x
67 template <class R, class... Args>
68 typename detail::make_member_proxy<R, Args...>::type call(
69 char const* name, Args const&... args) const
71 lua_State* L = m_self.state();
72 m_self.get(L);
73 assert(!lua_isnil(L, -1));
74 detail::do_call_member_selection(L, name);
76 if (lua_isnil(L, -1))
78 lua_pop(L, 1);
79 throw std::runtime_error("Attempt to call nonexistent function");
82 // push the self reference as the first parameter
83 m_self.get(L);
85 typedef typename detail::make_member_proxy<R, Args...>::type
86 proxy_type;
87 return proxy_type(L, std::tuple<Args const*...>(&args...));
90 # else // LUABIND_CPP0x
92 #define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, <luabind/wrapper_base.hpp>, 1))
93 #include BOOST_PP_ITERATE()
95 # endif // LUABIND_CPP0x
97 private:
98 wrapped_self_t m_self;
101 # ifdef LUABIND_CPP0x
103 template <class R, class... Args>
104 typename detail::make_member_proxy<R, Args...>::type call_member(
105 wrap_base const* self, char const* name, Args const&... args)
107 return self->call<R>(name, args...);
110 # else // LUABIND_CPP0x
112 # define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, <luabind/wrapper_base.hpp>, 2))
113 #include BOOST_PP_ITERATE()
115 # endif // LUABIND_CPP0x
117 namespace detail
119 struct wrap_access
121 static wrapped_self_t const& ref(wrap_base const& b)
123 return b.m_self;
126 static wrapped_self_t& ref(wrap_base& b)
128 return b.m_self;
134 #endif // LUABIND_WRAPPER_BASE_HPP_INCLUDED
136 #elif BOOST_PP_ITERATION_FLAGS() == 1
138 #define LUABIND_TUPLE_PARAMS(z, n, data) const A##n *
139 #define LUABIND_OPERATOR_PARAMS(z, n, data) const A##n & a##n
141 template<class R BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A)>
142 typename boost::mpl::if_<boost::is_void<R>
143 , luabind::detail::proxy_member_void_caller<boost::tuples::tuple<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS, _)> >
144 , luabind::detail::proxy_member_caller<R, boost::tuples::tuple<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS, _)> > >::type
145 call(char const* name BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_OPERATOR_PARAMS, _), detail::type_<R>* = 0) const
147 typedef boost::tuples::tuple<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS, _)> tuple_t;
148 #if BOOST_PP_ITERATION() == 0
149 tuple_t args;
150 #else
151 tuple_t args(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), &a));
152 #endif
154 typedef typename boost::mpl::if_<boost::is_void<R>
155 , luabind::detail::proxy_member_void_caller<boost::tuples::tuple<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS, _)> >
156 , luabind::detail::proxy_member_caller<R, boost::tuples::tuple<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS, _)> > >::type proxy_type;
158 // this will be cleaned up by the proxy object
159 // once the call has been made
161 // TODO: what happens if this virtual function is
162 // dispatched from a lua thread where the state
163 // pointer is different?
165 // get the function
166 lua_State* L = m_self.state();
167 m_self.get(L);
168 assert(!lua_isnil(L, -1));
169 detail::do_call_member_selection(L, name);
171 if (lua_isnil(L, -1))
173 lua_pop(L, 1);
174 throw std::runtime_error("Attempt to call nonexistent function");
177 // push the self reference as the first parameter
178 m_self.get(L);
180 // now the function and self objects
181 // are on the stack. These will both
182 // be popped by pcall
183 return proxy_type(L, args);
186 #undef LUABIND_CALL_MEMBER_NAME
187 #undef LUABIND_OPERATOR_PARAMS
188 #undef LUABIND_TUPLE_PARAMS
190 #else // free call_member forwardarding functions
192 #define N BOOST_PP_ITERATION()
194 #define LUABIND_TUPLE_PARAMS(z, n, data) const A##n *
195 #define LUABIND_OPERATOR_PARAMS(z, n, data) const A##n & a##n
197 template<
198 class R
199 BOOST_PP_ENUM_TRAILING_PARAMS(N, class A)
201 typename boost::mpl::if_<
202 boost::is_void<R>
203 , detail::proxy_member_void_caller<
204 boost::tuples::tuple<
205 BOOST_PP_ENUM(N, LUABIND_TUPLE_PARAMS, _)
208 , detail::proxy_member_caller<
210 , boost::tuples::tuple<
211 BOOST_PP_ENUM(N, LUABIND_TUPLE_PARAMS, _)
214 >::type
215 call_member(
216 wrap_base const* self
217 , char const* fn
218 BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(N, A, &a)
219 , detail::type_<R>* = 0
222 return self->call(
224 BOOST_PP_ENUM_TRAILING_PARAMS(N, a)
225 , (detail::type_<R>*)0
229 #undef LUABIND_OPERATOR_PARAMS
230 #undef LUABIND_TUPLE_PARAMS
232 #undef N
234 #endif