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