1 // Copyright (c) 2003 Daniel Wallin and Arvid Norberg 2 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: 9 10 // The above copyright notice and this permission notice shall be included 11 // in all copies or substantial portions of the Software. 12 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. 22 23 #ifndef LUABIND_OBJECT_PROXY_HPP_INCLUDED 24 #define LUABIND_OBJECT_PROXY_HPP_INCLUDED 25 26 #include <boost/optional.hpp> 27 28 #include <luabind/config.hpp> 29 #include <luabind/detail/policy.hpp> 30 #include <luabind/error.hpp> 31 #include <luabind/detail/convert_to_lua.hpp> 32 #include <luabind/detail/debug.hpp> 33 #include <luabind/detail/stack_utils.hpp> 34 35 #include <boost/mpl/apply_wrap.hpp> 36 37 namespace luabind 38 { 39 40 namespace detail 41 { 42 43 namespace mpl = boost::mpl; 44 45 template<class T, class Obj, class Policies> object_cast_impl(const Obj & obj,const Policies &)46 inline T object_cast_impl(const Obj& obj, const Policies&) 47 { 48 if (obj.lua_state() == 0) 49 { 50 #ifndef LUABIND_NO_EXCEPTIONS 51 throw cast_failed(0, typeid(T)); 52 #else 53 lua_State* L = obj.lua_state(); 54 cast_failed_callback_fun e = get_cast_failed_callback(); 55 if (e) e(L, typeid(T)); 56 57 assert(0 && "object_cast failed. If you want to handle this error use luabind::set_error_callback()"); 58 std::terminate(); 59 #endif 60 } 61 62 LUABIND_CHECK_STACK(obj.lua_state()); 63 64 typedef typename detail::find_conversion_policy<0, Policies>::type converter_policy; 65 typename mpl::apply_wrap2<converter_policy,T,lua_to_cpp>::type converter; 66 67 obj.pushvalue(); 68 69 lua_State* L = obj.lua_state(); 70 detail::stack_pop p(L, 1); 71 72 #ifndef LUABIND_NO_ERROR_CHECKING 73 74 if (converter.match(L, LUABIND_DECORATE_TYPE(T), -1) < 0) 75 { 76 #ifndef LUABIND_NO_EXCEPTIONS 77 throw cast_failed(L, typeid(T)); 78 #else 79 cast_failed_callback_fun e = get_cast_failed_callback(); 80 if (e) e(L, typeid(T)); 81 82 assert(0 && "object_cast failed. If you want to handle this error use luabind::set_error_callback()"); 83 std::terminate(); 84 #endif 85 } 86 #endif 87 88 return converter.apply(L, LUABIND_DECORATE_TYPE(T), -1); 89 } 90 91 template<class T, class Obj, class Policies> object_cast_nothrow_impl(const Obj & obj,const Policies &)92 boost::optional<T> object_cast_nothrow_impl(const Obj& obj, const Policies&) 93 { 94 typedef typename detail::find_conversion_policy<0, Policies>::type converter_policy; 95 typename mpl::apply_wrap2<converter_policy,T,lua_to_cpp>::type converter; 96 97 if (obj.lua_state() == 0) return boost::optional<T>(); 98 LUABIND_CHECK_STACK(obj.lua_state()); 99 100 obj.pushvalue(); 101 102 lua_State* L = obj.lua_state(); 103 detail::stack_pop p(L, 1); 104 105 #ifndef LUABIND_NO_ERROR_CHECKING 106 107 if (converter.match(L, LUABIND_DECORATE_TYPE(T), -1) < 0) 108 return boost::optional<T>(); 109 #endif 110 111 return boost::optional<T>(converter.apply(L, LUABIND_DECORATE_TYPE(T), -1)); 112 } 113 } 114 115 template<class T> object_cast(const object & obj)116 T object_cast(const object& obj) 117 { return detail::object_cast_impl<T>(obj, detail::null_type()); } 118 119 template<class T, class Policies> 120 T object_cast(const object& obj, const Policies& p) 121 { return detail::object_cast_impl<T>(obj, p); } 122 123 template<class T> object_cast_nothrow(const object & obj)124 boost::optional<T> object_cast_nothrow(const object& obj) 125 { return detail::object_cast_nothrow_impl<T>(obj, detail::null_type()); } 126 127 template<class T, class Policies> object_cast_nothrow(const object & obj,const Policies & p)128 boost::optional<T> object_cast_nothrow(const object& obj, const Policies& p) 129 { return detail::object_cast_nothrow_impl<T>(obj, p); } 130 131 132 template<class T> object_cast(const detail::proxy_object & obj)133 T object_cast(const detail::proxy_object& obj) 134 { return detail::object_cast_impl<T>(obj, detail::null_type()); } 135 136 template<class T, class Policies> 137 T object_cast(const detail::proxy_object& obj, const Policies& p) 138 { return detail::object_cast_impl<T>(obj, p); } 139 140 template<class T> object_cast_nothrow(const detail::proxy_object & obj)141 boost::optional<T> object_cast_nothrow(const detail::proxy_object& obj) 142 { return detail::object_cast_nothrow_impl<T>(obj, detail::null_type()); } 143 144 template<class T, class Policies> object_cast_nothrow(const detail::proxy_object & obj,const Policies & p)145 boost::optional<T> object_cast_nothrow(const detail::proxy_object& obj, const Policies& p) 146 { return detail::object_cast_nothrow_impl<T>(obj, p); } 147 148 149 template<class T> object_cast(const detail::proxy_raw_object & obj)150 T object_cast(const detail::proxy_raw_object& obj) 151 { return detail::object_cast_impl<T>(obj, detail::null_type()); } 152 153 template<class T, class Policies> 154 T object_cast(const detail::proxy_raw_object& obj, const Policies& p) 155 { return detail::object_cast_impl<T>(obj, p); } 156 157 template<class T> object_cast_nothrow(const detail::proxy_raw_object & obj)158 boost::optional<T> object_cast_nothrow(const detail::proxy_raw_object& obj) 159 { return detail::object_cast_nothrow_impl<T>(obj, detail::null_type()); } 160 161 template<class T, class Policies> object_cast_nothrow(const detail::proxy_raw_object & obj,const Policies & p)162 boost::optional<T> object_cast_nothrow(const detail::proxy_raw_object& obj, const Policies& p) 163 { return detail::object_cast_nothrow_impl<T>(obj, p); } 164 165 166 template<class T> object_cast(const detail::proxy_array_object & obj)167 T object_cast(const detail::proxy_array_object& obj) 168 { return detail::object_cast_impl<T>(obj, detail::null_type()); } 169 170 template<class T, class Policies> 171 T object_cast(const detail::proxy_array_object& obj, const Policies& p) 172 { return detail::object_cast_impl<T>(obj, p); } 173 174 template<class T> object_cast_nothrow(const detail::proxy_array_object & obj)175 boost::optional<T> object_cast_nothrow(const detail::proxy_array_object& obj) 176 { return detail::object_cast_nothrow_impl<T>(obj, detail::null_type()); } 177 178 template<class T, class Policies> object_cast_nothrow(const detail::proxy_array_object & obj,const Policies & p)179 boost::optional<T> object_cast_nothrow(const detail::proxy_array_object& obj, const Policies& p) 180 { return detail::object_cast_nothrow_impl<T>(obj, p); } 181 182 183 184 get_globals(lua_State * L)185 inline object get_globals(lua_State* L) 186 { 187 lua_pushvalue(L, LUA_GLOBALSINDEX); 188 detail::lua_reference ref; 189 ref.set(L); 190 return object(L, ref, true/*object::reference()*/); 191 } 192 get_registry(lua_State * L)193 inline object get_registry(lua_State* L) 194 { 195 lua_pushvalue(L, LUA_REGISTRYINDEX); 196 detail::lua_reference ref; 197 ref.set(L); 198 return object(L, ref, true/*object::reference()*/); 199 } 200 newtable(lua_State * L)201 inline object newtable(lua_State* L) 202 { 203 lua_newtable(L); 204 detail::lua_reference ref; 205 ref.set(L); 206 return object(L, ref, true/*object::reference()*/); 207 } 208 } 209 210 /* 211 212 struct A 213 { 214 }; 215 216 object f = class_<A>(); 217 218 A* ptr = object_cast<A*>(f(), adopt(_1)); 219 220 delete ptr; 221 222 */ 223 224 #endif // LUABIND_OBJECT_PROXY_HPP_INCLUDED 225