wrapper_base.hpp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. // Copyright (c) 2003 Daniel Wallin and Arvid Norberg
  2. // Permission is hereby granted, free of charge, to any person obtaining a
  3. // copy of this software and associated documentation files (the "Software"),
  4. // to deal in the Software without restriction, including without limitation
  5. // the rights to use, copy, modify, merge, publish, distribute, sublicense,
  6. // and/or sell copies of the Software, and to permit persons to whom the
  7. // Software is furnished to do so, subject to the following conditions:
  8. // The above copyright notice and this permission notice shall be included
  9. // in all copies or substantial portions of the Software.
  10. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
  11. // ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
  12. // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
  13. // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
  14. // SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
  15. // ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  16. // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  17. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
  18. // OR OTHER DEALINGS IN THE SOFTWARE.
  19. #if !BOOST_PP_IS_ITERATING
  20. #ifndef LUABIND_WRAPPER_BASE_HPP_INCLUDED
  21. #define LUABIND_WRAPPER_BASE_HPP_INCLUDED
  22. #include <luabind/config.hpp>
  23. #include <luabind/weak_ref.hpp>
  24. #include <luabind/detail/ref.hpp>
  25. #include <luabind/detail/call_member.hpp>
  26. #ifndef LUABIND_CPP0x
  27. # include <boost/preprocessor/repetition/enum_trailing_params.hpp>
  28. # include <boost/preprocessor/repetition/enum_trailing_binary_params.hpp>
  29. #endif
  30. #include <stdexcept>
  31. namespace luabind
  32. {
  33. namespace detail
  34. {
  35. struct wrap_access;
  36. // implements the selection between dynamic dispatch
  37. // or default implementation calls from within a virtual
  38. // function wrapper. The input is the self reference on
  39. // the top of the stack. Output is the function to call
  40. // on the top of the stack (the input self reference will
  41. // be popped)
  42. LUABIND_API void do_call_member_selection(lua_State* L, char const* name);
  43. }
  44. struct wrapped_self_t: weak_ref
  45. {
  46. detail::lua_reference m_strong_ref;
  47. };
  48. struct wrap_base
  49. {
  50. friend struct detail::wrap_access;
  51. wrap_base() {}
  52. # ifdef LUABIND_CPP0x
  53. template <class R, class... Args>
  54. typename detail::make_member_proxy<R, Args...>::type call(
  55. char const* name, Args const&... args) const
  56. {
  57. lua_State* L = m_self.state();
  58. m_self.get(L);
  59. assert(!lua_isnil(L, -1));
  60. detail::do_call_member_selection(L, name);
  61. if (lua_isnil(L, -1))
  62. {
  63. lua_pop(L, 1);
  64. throw std::runtime_error("Attempt to call nonexistent function");
  65. }
  66. // push the self reference as the first parameter
  67. m_self.get(L);
  68. typedef typename detail::make_member_proxy<R, Args...>::type
  69. proxy_type;
  70. return proxy_type(L, std::tuple<Args const*...>(&args...));
  71. }
  72. # else // LUABIND_CPP0x
  73. #define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, <luabind/wrapper_base.hpp>, 1))
  74. #include BOOST_PP_ITERATE()
  75. # endif // LUABIND_CPP0x
  76. private:
  77. wrapped_self_t m_self;
  78. };
  79. # ifdef LUABIND_CPP0x
  80. template <class R, class... Args>
  81. typename detail::make_member_proxy<R, Args...>::type call_member(
  82. wrap_base const* self, char const* name, Args const&... args)
  83. {
  84. return self->call<R>(name, args...);
  85. }
  86. # else // LUABIND_CPP0x
  87. # define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, <luabind/wrapper_base.hpp>, 2))
  88. #include BOOST_PP_ITERATE()
  89. # endif // LUABIND_CPP0x
  90. namespace detail
  91. {
  92. struct wrap_access
  93. {
  94. static wrapped_self_t const& ref(wrap_base const& b)
  95. {
  96. return b.m_self;
  97. }
  98. static wrapped_self_t& ref(wrap_base& b)
  99. {
  100. return b.m_self;
  101. }
  102. };
  103. }
  104. }
  105. #endif // LUABIND_WRAPPER_BASE_HPP_INCLUDED
  106. #else
  107. #if BOOST_PP_ITERATION_FLAGS() == 1
  108. #define LUABIND_TUPLE_PARAMS(z, n, data) const A##n *
  109. #define LUABIND_OPERATOR_PARAMS(z, n, data) const A##n & a##n
  110. template<class R BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A)>
  111. typename boost::mpl::if_<boost::is_void<R>
  112. , luabind::detail::proxy_member_void_caller<boost::tuples::tuple<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS, _)> >
  113. , luabind::detail::proxy_member_caller<R, boost::tuples::tuple<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS, _)> > >::type
  114. 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
  115. {
  116. typedef boost::tuples::tuple<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS, _)> tuple_t;
  117. #if BOOST_PP_ITERATION() == 0
  118. tuple_t args;
  119. #else
  120. tuple_t args(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), &a));
  121. #endif
  122. typedef typename boost::mpl::if_<boost::is_void<R>
  123. , luabind::detail::proxy_member_void_caller<boost::tuples::tuple<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS, _)> >
  124. , luabind::detail::proxy_member_caller<R, boost::tuples::tuple<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS, _)> > >::type proxy_type;
  125. // this will be cleaned up by the proxy object
  126. // once the call has been made
  127. // TODO: what happens if this virtual function is
  128. // dispatched from a lua thread where the state
  129. // pointer is different?
  130. // get the function
  131. lua_State* L = m_self.state();
  132. m_self.get(L);
  133. assert(!lua_isnil(L, -1));
  134. detail::do_call_member_selection(L, name);
  135. if (lua_isnil(L, -1))
  136. {
  137. lua_pop(L, 1);
  138. throw std::runtime_error("Attempt to call nonexistent function");
  139. }
  140. // push the self reference as the first parameter
  141. m_self.get(L);
  142. // now the function and self objects
  143. // are on the stack. These will both
  144. // be popped by pcall
  145. return proxy_type(L, args);
  146. }
  147. #undef LUABIND_CALL_MEMBER_NAME
  148. #undef LUABIND_OPERATOR_PARAMS
  149. #undef LUABIND_TUPLE_PARAMS
  150. #else // free call_member forwardarding functions
  151. #define N BOOST_PP_ITERATION()
  152. #define LUABIND_TUPLE_PARAMS(z, n, data) const A##n *
  153. #define LUABIND_OPERATOR_PARAMS(z, n, data) const A##n & a##n
  154. template<
  155. class R
  156. BOOST_PP_ENUM_TRAILING_PARAMS(N, class A)
  157. >
  158. typename boost::mpl::if_<
  159. boost::is_void<R>
  160. , detail::proxy_member_void_caller<
  161. boost::tuples::tuple<
  162. BOOST_PP_ENUM(N, LUABIND_TUPLE_PARAMS, _)
  163. >
  164. >
  165. , detail::proxy_member_caller<
  166. R
  167. , boost::tuples::tuple<
  168. BOOST_PP_ENUM(N, LUABIND_TUPLE_PARAMS, _)
  169. >
  170. >
  171. >::type
  172. call_member(
  173. wrap_base const* self
  174. , char const* fn
  175. BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(N, A, &a)
  176. , detail::type_<R>* = 0
  177. )
  178. {
  179. return self->call(
  180. fn
  181. BOOST_PP_ENUM_TRAILING_PARAMS(N, a)
  182. , (detail::type_<R>*)0
  183. );
  184. }
  185. #undef LUABIND_OPERATOR_PARAMS
  186. #undef LUABIND_TUPLE_PARAMS
  187. #undef N
  188. #endif
  189. #endif