Fix bug when passing type with holder by value to Lua.
[luabind.git] / luabind / detail / policy.hpp
blobe1d62d18a00ff3599633d9f473b69f9a22621fbd
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 #ifndef LUABIND_POLICY_HPP_INCLUDED
25 #define LUABIND_POLICY_HPP_INCLUDED
27 #include <luabind/config.hpp>
29 #include <typeinfo>
30 #include <string>
32 #include <boost/type_traits/is_enum.hpp>
33 #include <boost/type_traits/is_array.hpp>
34 #include <boost/mpl/bool.hpp>
35 #include <boost/mpl/integral_c.hpp>
36 #include <boost/mpl/equal_to.hpp>
37 #include <boost/mpl/eval_if.hpp>
38 #include <boost/mpl/or.hpp>
39 #include <boost/type_traits/add_reference.hpp>
40 #include <boost/type_traits/remove_reference.hpp>
41 #include <boost/type_traits/is_pointer.hpp>
42 #include <boost/type_traits/is_base_and_derived.hpp>
43 #include <boost/bind/arg.hpp>
44 #include <boost/limits.hpp>
45 #include <boost/tuple/tuple.hpp>
46 #include <boost/version.hpp>
48 #include <luabind/detail/class_registry.hpp>
49 #include <luabind/detail/primitives.hpp>
50 #include <luabind/detail/object_rep.hpp>
51 #include <luabind/detail/typetraits.hpp>
52 #include <luabind/detail/class_cache.hpp>
53 #include <luabind/detail/debug.hpp>
54 #include <luabind/detail/class_rep.hpp>
56 #include <boost/type_traits/add_reference.hpp>
58 #include <luabind/detail/decorate_type.hpp>
59 #include <luabind/weak_ref.hpp>
60 #include <luabind/back_reference_fwd.hpp>
62 #include <luabind/value_wrapper.hpp>
63 #include <luabind/from_stack.hpp>
65 namespace luabind
67 namespace detail
69 struct conversion_policy_base {};
72 template<int N, bool HasArg = true>
73 struct conversion_policy : detail::conversion_policy_base
75 BOOST_STATIC_CONSTANT(int, index = N);
76 BOOST_STATIC_CONSTANT(bool, has_arg = HasArg);
79 class index_map
81 public:
82 index_map(const int* m): m_map(m) {}
84 int operator[](int index) const
86 return m_map[index];
89 private:
90 const int* m_map;
93 namespace converters
95 using luabind::detail::yes_t;
96 using luabind::detail::no_t;
97 using luabind::detail::by_value;
98 using luabind::detail::by_reference;
99 using luabind::detail::by_const_reference;
100 using luabind::detail::by_pointer;
101 using luabind::detail::by_const_pointer;
103 no_t is_user_defined(...);
106 namespace detail
108 template<class T>
109 struct is_user_defined
111 BOOST_STATIC_CONSTANT(bool, value =
112 sizeof(luabind::converters::is_user_defined(LUABIND_DECORATE_TYPE(T))) == sizeof(yes_t));
115 LUABIND_API int implicit_cast(const class_rep* crep, LUABIND_TYPE_INFO const&, int& pointer_offset);
118 // template<class T> class functor;
119 class weak_ref;
122 namespace luabind { namespace detail
124 template<class>
125 struct is_primitive;
127 template<class T>
128 yes_t is_lua_functor_test(const functor<T>&);
130 #if defined(BOOST_MSVC) && (BOOST_MSVC <= 1300)
131 no_t is_lua_functor_test(...);
132 #else
133 template<class T>
134 no_t is_lua_functor_test(const T&);
135 #endif
137 template<class T>
138 struct is_lua_functor
140 static T t;
142 BOOST_STATIC_CONSTANT(bool, value = sizeof(is_lua_functor_test(t)) == sizeof(yes_t));
145 template<class H, class T>
146 struct policy_cons
148 typedef H head;
149 typedef T tail;
151 template<class U>
152 policy_cons<U, policy_cons<H,T> > operator,(policy_cons<U,detail::null_type>)
154 return policy_cons<U, policy_cons<H,T> >();
157 template<class U>
158 policy_cons<U, policy_cons<H,T> > operator+(policy_cons<U,detail::null_type>)
160 return policy_cons<U, policy_cons<H,T> >();
163 template<class U>
164 policy_cons<U, policy_cons<H,T> > operator|(policy_cons<U,detail::null_type>)
166 return policy_cons<U, policy_cons<H,T> >();
170 struct indirection_layer
172 template<class T>
173 indirection_layer(const T&);
176 yes_t is_policy_cons_test(const null_type&);
177 template<class H, class T>
178 yes_t is_policy_cons_test(const policy_cons<H,T>&);
179 no_t is_policy_cons_test(...);
181 template<class T>
182 struct is_policy_cons
184 static const T& t;
186 BOOST_STATIC_CONSTANT(bool, value =
187 sizeof(is_policy_cons_test(t)) == sizeof(yes_t));
189 typedef boost::mpl::bool_<value> type;
192 template<bool>
193 struct is_string_literal
195 static no_t helper(indirection_layer);
196 static yes_t helper(const char*);
199 template<>
200 struct is_string_literal<false>
202 static no_t helper(indirection_layer);
206 template<class T>
207 struct is_primitive/*: boost::mpl::bool_c<false>*/
209 static T t;
211 BOOST_STATIC_CONSTANT(bool, value =
212 sizeof(is_string_literal<boost::is_array<T>::value>::helper(t)) == sizeof(yes_t));
215 #define LUABIND_INTEGER_TYPE(type) \
216 template<> struct is_primitive<type> : boost::mpl::true_ {}; \
217 template<> struct is_primitive<type const> : boost::mpl::true_ {}; \
218 template<> struct is_primitive<type const&> : boost::mpl::true_ {}; \
219 template<> struct is_primitive<unsigned type> : boost::mpl::true_ {}; \
220 template<> struct is_primitive<unsigned type const> : boost::mpl::true_ {}; \
221 template<> struct is_primitive<unsigned type const&> : boost::mpl::true_ {};
223 LUABIND_INTEGER_TYPE(char)
224 LUABIND_INTEGER_TYPE(short)
225 LUABIND_INTEGER_TYPE(int)
226 LUABIND_INTEGER_TYPE(long)
228 template<> struct is_primitive<signed char> : boost::mpl::true_ {}; \
229 template<> struct is_primitive<signed char const> : boost::mpl::true_ {}; \
230 template<> struct is_primitive<signed char const&> : boost::mpl::true_ {}; \
232 #undef LUABIND_INTEGER_TYPE
234 template<> struct is_primitive<luabind::weak_ref>: boost::mpl::bool_<true> {};
235 template<> struct is_primitive<const luabind::weak_ref>: boost::mpl::bool_<true> {};
236 template<> struct is_primitive<const luabind::weak_ref&>: boost::mpl::bool_<true> {};
238 template<> struct is_primitive<float>: boost::mpl::bool_<true> {};
239 template<> struct is_primitive<double>: boost::mpl::bool_<true> {};
240 template<> struct is_primitive<long double>: boost::mpl::bool_<true> {};
241 template<> struct is_primitive<char*>: boost::mpl::bool_<true> {};
242 template<> struct is_primitive<bool>: boost::mpl::bool_<true> {};
244 template<> struct is_primitive<const float>: boost::mpl::bool_<true> {};
245 template<> struct is_primitive<const double>: boost::mpl::bool_<true> {};
246 template<> struct is_primitive<const long double>: boost::mpl::bool_<true> {};
247 template<> struct is_primitive<const char*>: boost::mpl::bool_<true> {};
248 template<> struct is_primitive<const char* const>: boost::mpl::bool_<true> {};
249 template<> struct is_primitive<const bool>: boost::mpl::bool_<true> {};
251 // TODO: add more
252 template<> struct is_primitive<const float&>: boost::mpl::bool_<true> {};
253 template<> struct is_primitive<const double&>: boost::mpl::bool_<true> {};
254 template<> struct is_primitive<const long double&>: boost::mpl::bool_<true> {};
255 template<> struct is_primitive<const bool&>: boost::mpl::bool_<true> {};
257 template<> struct is_primitive<const std::string&>: boost::mpl::bool_<true> {};
258 template<> struct is_primitive<std::string>: boost::mpl::bool_<true> {};
259 template<> struct is_primitive<const std::string>: boost::mpl::bool_<true> {};
262 template<class Direction> struct primitive_converter;
264 template<>
265 struct primitive_converter<cpp_to_lua>
267 typedef boost::mpl::bool_<false> is_value_converter;
268 typedef primitive_converter type;
270 void apply(lua_State* L, int v) { lua_pushnumber(L, (lua_Number)v); }
271 void apply(lua_State* L, short v) { lua_pushnumber(L, (lua_Number)v); }
272 void apply(lua_State* L, char v) { lua_pushnumber(L, (lua_Number)v); }
273 void apply(lua_State* L, long v) { lua_pushnumber(L, (lua_Number)v); }
274 void apply(lua_State* L, unsigned int v) { lua_pushnumber(L, (lua_Number)v); }
275 void apply(lua_State* L, unsigned short v) { lua_pushnumber(L, (lua_Number)v); }
276 void apply(lua_State* L, unsigned char v) { lua_pushnumber(L, (lua_Number)v); }
277 void apply(lua_State* L, unsigned long v) { lua_pushnumber(L, (lua_Number)v); }
278 void apply(lua_State* L, float v) { lua_pushnumber(L, (lua_Number)v); }
279 void apply(lua_State* L, double v) { lua_pushnumber(L, (lua_Number)v); }
280 void apply(lua_State* L, long double v) { lua_pushnumber(L, (lua_Number)v); }
281 void apply(lua_State* L, const char* v)
283 if (v)
285 lua_pushstring(L, v);
287 else
289 lua_pushnil(L);
292 void apply(lua_State* L, const std::string& v)
293 { lua_pushlstring(L, v.data(), v.size()); }
294 void apply(lua_State* L, bool b) { lua_pushboolean(L, b); }
297 template<>
298 struct primitive_converter<lua_to_cpp>
300 typedef boost::mpl::bool_<false> is_value_converter;
301 typedef primitive_converter type;
303 #define PRIMITIVE_CONVERTER(prim) \
304 prim apply(lua_State* L, luabind::detail::by_const_reference<prim>, int index) { return apply(L, detail::by_value<prim>(), index); } \
305 prim apply(lua_State* L, luabind::detail::by_value<const prim>, int index) { return apply(L, detail::by_value<prim>(), index); } \
306 prim apply(lua_State* L, luabind::detail::by_value<prim>, int index)
308 #define PRIMITIVE_MATCHER(prim) \
309 static int match(lua_State* L, luabind::detail::by_const_reference<prim>, int index) { return match(L, detail::by_value<prim>(), index); } \
310 static int match(lua_State* L, luabind::detail::by_value<const prim>, int index) { return match(L, detail::by_value<prim>(), index); } \
311 static int match(lua_State* L, luabind::detail::by_value<prim>, int index)
313 PRIMITIVE_CONVERTER(bool) { return lua_toboolean(L, index) == 1; }
314 PRIMITIVE_MATCHER(bool) { if (lua_type(L, index) == LUA_TBOOLEAN) return 0; else return -1; }
316 PRIMITIVE_CONVERTER(int) { return static_cast<int>(lua_tonumber(L, index)); }
317 PRIMITIVE_MATCHER(int) { if (lua_type(L, index) == LUA_TNUMBER) return 0; else return -1; }
319 PRIMITIVE_CONVERTER(unsigned int) { return static_cast<unsigned int>(lua_tonumber(L, index)); }
320 PRIMITIVE_MATCHER(unsigned int) { if (lua_type(L, index) == LUA_TNUMBER) return 0; else return -1; }
322 PRIMITIVE_CONVERTER(char) { return static_cast<char>(lua_tonumber(L, index)); }
323 PRIMITIVE_MATCHER(char) { if (lua_type(L, index) == LUA_TNUMBER) return 0; else return -1; }
325 PRIMITIVE_CONVERTER(signed char) { return static_cast<char>(lua_tonumber(L, index)); }
326 PRIMITIVE_MATCHER(signed char) { if (lua_type(L, index) == LUA_TNUMBER) return 0; else return -1; }
328 PRIMITIVE_CONVERTER(unsigned char) { return static_cast<unsigned char>(lua_tonumber(L, index)); }
329 PRIMITIVE_MATCHER(unsigned char) { if (lua_type(L, index) == LUA_TNUMBER) return 0; else return -1; }
331 PRIMITIVE_CONVERTER(short) { return static_cast<short>(lua_tonumber(L, index)); }
332 PRIMITIVE_MATCHER(short) { if (lua_type(L, index) == LUA_TNUMBER) return 0; else return -1; }
334 PRIMITIVE_CONVERTER(unsigned short) { return static_cast<unsigned short>(lua_tonumber(L, index)); }
335 PRIMITIVE_MATCHER(unsigned short) { if (lua_type(L, index) == LUA_TNUMBER) return 0; else return -1; }
337 PRIMITIVE_CONVERTER(long) { return static_cast<long>(lua_tonumber(L, index)); }
338 PRIMITIVE_MATCHER(long) { if (lua_type(L, index) == LUA_TNUMBER) return 0; else return -1; }
340 PRIMITIVE_CONVERTER(unsigned long) { return static_cast<unsigned long>(lua_tonumber(L, index)); }
341 PRIMITIVE_MATCHER(unsigned long) { if (lua_type(L, index) == LUA_TNUMBER) return 0; else return -1; }
343 PRIMITIVE_CONVERTER(float) { return static_cast<float>(lua_tonumber(L, index)); }
344 PRIMITIVE_MATCHER(float) { if (lua_type(L, index) == LUA_TNUMBER) return 0; else return -1; }
346 PRIMITIVE_CONVERTER(double) { return static_cast<double>(lua_tonumber(L, index)); }
347 PRIMITIVE_MATCHER(double) { if (lua_type(L, index) == LUA_TNUMBER) return 0; else return -1; }
349 PRIMITIVE_CONVERTER(lua_State*) { return lua_tothread(L, index); }
350 PRIMITIVE_MATCHER(lua_State*) { if (lua_type(L, index) == LUA_TTHREAD) return 0; else return -1; }
352 PRIMITIVE_CONVERTER(std::string)
353 { return std::string(lua_tostring(L, index), lua_strlen(L, index)); }
354 PRIMITIVE_MATCHER(std::string) { if (lua_type(L, index) == LUA_TSTRING) return 0; else return -1; }
356 PRIMITIVE_CONVERTER(luabind::weak_ref)
358 LUABIND_CHECK_STACK(L);
359 return luabind::weak_ref(L, index);
362 PRIMITIVE_MATCHER(luabind::weak_ref) { (void)index; (void)L; return (std::numeric_limits<int>::max)() - 1; }
364 const char* apply(lua_State* L, detail::by_const_pointer<char>, int index)
366 return static_cast<const char*>(lua_tostring(L, index));
369 const char* apply(lua_State* L, detail::by_const_pointer<const char>, int index)
371 return static_cast<const char*>(lua_tostring(L, index));
374 static int match(lua_State* L, by_const_pointer<char>, int index)
376 return lua_type(L, index) == LUA_TSTRING
377 || lua_isnil(L, index) ? 0 : -1;
379 static int match(lua_State* L, by_const_pointer<const char>, int index)
381 return lua_type(L, index) == LUA_TSTRING
382 || lua_isnil(L, index) ? 0 : -1;
385 template<class T>
386 void converter_postcall(lua_State*, T, int) {}
388 #undef PRIMITIVE_MATCHER
389 #undef PRIMITIVE_CONVERTER
394 // ********** user defined converter ***********
396 template<class Direction> struct user_defined_converter;
398 template<>
399 struct user_defined_converter<lua_to_cpp>
401 typedef boost::mpl::bool_<false> is_value_converter;
402 typedef user_defined_converter type;
404 template<class T>
405 T apply(lua_State* L, detail::by_value<T>, int index)
407 using namespace converters;
408 return convert_lua_to_cpp(L, detail::by_value<T>(), index);
411 template<class T>
412 T apply(lua_State* L, detail::by_reference<T>, int index)
414 using namespace converters;
415 return convert_lua_to_cpp(L, detail::by_reference<T>(), index);
418 template<class T>
419 T apply(lua_State* L, detail::by_const_reference<T>, int index)
421 using namespace converters;
422 return convert_lua_to_cpp(L, detail::by_const_reference<T>(), index);
425 template<class T>
426 T* apply(lua_State* L, detail::by_pointer<T>, int index)
428 using namespace converters;
429 return convert_lua_to_cpp(L, detail::by_pointer<T>(), index);
432 template<class T>
433 const T* apply(lua_State* L, detail::by_const_pointer<T>, int index)
435 using namespace converters;
436 return convert_lua_to_cpp(L, detail::by_pointer<T>(), index);
439 template<class T>
440 static int match(lua_State* L, T, int index)
442 using namespace converters;
443 return match_lua_to_cpp(L, T(), index);
446 template<class T>
447 void converter_postcall(lua_State*, T, int) {}
450 template<>
451 struct user_defined_converter<cpp_to_lua>
453 typedef boost::mpl::bool_<false> is_value_converter;
454 typedef user_defined_converter type;
456 template<class T>
457 void apply(lua_State* L, const T& v)
459 using namespace converters;
460 convert_cpp_to_lua(L, v);
464 // ********** pointer converter ***********
467 template<class Direction> struct pointer_converter;
469 template<>
470 struct pointer_converter<cpp_to_lua>
472 typedef boost::mpl::bool_<false> is_value_converter;
473 typedef pointer_converter type;
475 template<class T>
476 void apply(lua_State* L, T* ptr)
478 if (ptr == 0)
480 lua_pushnil(L);
481 return;
484 if (luabind::get_back_reference(L, ptr))
485 return;
487 class_rep* crep = get_class_rep<T>(L);
489 // if you get caught in this assert you are
490 // trying to use an unregistered type
491 assert(crep && "you are trying to use an unregistered type");
493 // create the struct to hold the object
494 void* obj = lua_newuserdata(L, sizeof(object_rep));
495 //new(obj) object_rep(ptr, crep, object_rep::owner, destructor_s<T>::apply);
496 new(obj) object_rep(ptr, crep, 0, 0);
498 // set the meta table
499 detail::getref(L, crep->metatable_ref());
500 lua_setmetatable(L, -2);
504 template<class T> struct make_pointer { typedef T* type; };
505 template<>
506 struct pointer_converter<lua_to_cpp>
508 typedef boost::mpl::bool_<false> is_value_converter;
509 typedef pointer_converter type;
511 // TODO: does the pointer converter need this?!
512 char target[32];
513 void (*destructor)(void *);
515 pointer_converter(): destructor(0) {}
517 template<class T>
518 typename make_pointer<T>::type apply(lua_State* L, by_pointer<T>, int index)
520 // preconditions:
521 // lua_isuserdata(L, index);
522 // getmetatable().__lua_class is true
523 // object_rep->flags() & object_rep::constant == 0
525 if (lua_isnil(L, index)) return 0;
527 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, index));
528 assert((obj != 0) && "internal error, please report"); // internal error
529 const class_rep* crep = obj->crep();
531 T* ptr = reinterpret_cast<T*>(crep->convert_to(LUABIND_TYPEID(T), obj, target));
533 if ((void*)ptr == (char*)target) destructor = detail::destruct_only_s<T>::apply;
534 assert(!destructor || sizeof(T) <= 32);
536 return ptr;
539 template<class T>
540 static int match(lua_State* L, by_pointer<T>, int index)
542 if (lua_isnil(L, index)) return 0;
543 object_rep* obj = is_class_object(L, index);
544 if (obj == 0) return -1;
545 // cannot cast a constant object to nonconst
546 if (obj->flags() & object_rep::constant) return -1;
548 if ((LUABIND_TYPE_INFO_EQUAL(obj->crep()->holder_type(), LUABIND_TYPEID(T))))
549 return (obj->flags() & object_rep::constant)?-1:0;
550 if ((LUABIND_TYPE_INFO_EQUAL(obj->crep()->const_holder_type(), LUABIND_TYPEID(T))))
551 return (obj->flags() & object_rep::constant)?0:-1;
553 int d;
554 return implicit_cast(obj->crep(), LUABIND_TYPEID(T), d);
557 ~pointer_converter()
559 if (destructor) destructor(target);
562 template<class T>
563 void converter_postcall(lua_State*, by_pointer<T>, int)
567 // ******* value converter *******
569 template<class Direction> struct value_converter;
571 template<>
572 struct value_converter<cpp_to_lua>
574 typedef boost::mpl::bool_<true> is_value_converter;
575 typedef value_converter type;
577 template<class T>
578 void apply(lua_State* L, const T& ref)
580 if (luabind::get_back_reference(L, ref))
581 return;
583 class_rep* crep = get_class_rep<T>(L);
585 // if you get caught in this assert you are
586 // trying to use an unregistered type
587 assert(crep && "you are trying to use an unregistered type");
589 void* obj_rep;
590 void* held;
592 boost::tie(obj_rep,held) = crep->allocate(L);
594 void* object_ptr;
595 void(*destructor)(void*);
596 destructor = crep->destructor();
597 int flags = object_rep::owner;
598 if (crep->has_holder())
600 if (LUABIND_TYPE_INFO_EQUAL(LUABIND_TYPEID(T), crep->const_holder_type()))
602 new(held) T(ref);
603 object_ptr = held;
604 flags |= object_rep::constant;
605 destructor = crep->const_holder_destructor();
607 else if (LUABIND_TYPE_INFO_EQUAL(LUABIND_TYPEID(T), crep->holder_type()))
609 new(held) T(ref);
610 object_ptr = held;
612 else
614 assert(LUABIND_TYPE_INFO_EQUAL(LUABIND_TYPEID(T), crep->type()));
615 std::auto_ptr<T> obj(new T(ref));
616 crep->construct_holder()(held, obj.get());
617 object_ptr = held;
618 obj.release();
621 else
623 object_ptr = new T(ref);
625 new(obj_rep) object_rep(object_ptr, crep, flags, destructor);
627 // set the meta table
628 detail::getref(L, crep->metatable_ref());
629 lua_setmetatable(L, -2);
634 template<class T> struct make_const_reference { typedef const T& type; };
636 template<class T>
637 struct destruct_guard
639 T* ptr;
640 bool dismiss;
641 destruct_guard(T* p): ptr(p), dismiss(false) {}
643 ~destruct_guard()
645 if (!dismiss)
646 ptr->~T();
650 template<>
651 struct value_converter<lua_to_cpp>
653 typedef boost::mpl::bool_<true> is_value_converter;
654 typedef value_converter type;
656 template<class T>
657 T apply(lua_State* L, by_value<T>, int index)
659 // preconditions:
660 // lua_isuserdata(L, index);
661 // getmetatable().__lua_class is true
662 // object_rep->flags() & object_rep::constant == 0
664 object_rep* obj = 0;
665 const class_rep* crep = 0;
667 // special case if we get nil in, try to convert the holder type
668 if (lua_isnil(L, index))
670 crep = get_class_rep<T>(L);
671 assert(crep);
673 else
675 obj = static_cast<object_rep*>(lua_touserdata(L, index));
676 assert((obj != 0) && "internal error, please report"); // internal error
677 crep = obj->crep();
679 assert(crep);
681 // TODO: align!
682 char target[sizeof(T)];
683 T* ptr = reinterpret_cast<T*>(crep->convert_to(LUABIND_TYPEID(T), obj, target));
685 destruct_guard<T> guard(ptr);
686 if ((void*)ptr != (void*)target) guard.dismiss = true;
688 return *ptr;
691 template<class T>
692 static int match(lua_State* L, by_value<T>, int index)
694 // special case if we get nil in, try to match the holder type
695 if (lua_isnil(L, index))
697 class_rep* crep = get_class_rep<T>(L);
698 if (crep == 0) return -1;
699 if ((LUABIND_TYPE_INFO_EQUAL(crep->holder_type(), LUABIND_TYPEID(T))))
700 return 0;
701 if ((LUABIND_TYPE_INFO_EQUAL(crep->const_holder_type(), LUABIND_TYPEID(T))))
702 return 0;
703 return -1;
706 object_rep* obj = is_class_object(L, index);
707 if (obj == 0) return -1;
708 int d;
710 if ((LUABIND_TYPE_INFO_EQUAL(obj->crep()->holder_type(), LUABIND_TYPEID(T))))
711 return (obj->flags() & object_rep::constant)?-1:0;
712 if ((LUABIND_TYPE_INFO_EQUAL(obj->crep()->const_holder_type(), LUABIND_TYPEID(T))))
713 return (obj->flags() & object_rep::constant)?0:1;
715 return implicit_cast(obj->crep(), LUABIND_TYPEID(T), d);
718 template<class T>
719 void converter_postcall(lua_State*, T, int) {}
722 // ******* const pointer converter *******
724 template<class Direction> struct const_pointer_converter;
726 template<>
727 struct const_pointer_converter<cpp_to_lua>
729 typedef boost::mpl::bool_<false> is_value_converter;
730 typedef const_pointer_converter type;
732 template<class T>
733 void apply(lua_State* L, const T* ptr)
735 if (ptr == 0)
737 lua_pushnil(L);
738 return;
741 if (luabind::get_back_reference(L, ptr))
742 return;
744 class_rep* crep = get_class_rep<T>(L);
746 // if you get caught in this assert you are
747 // trying to use an unregistered type
748 assert(crep && "you are trying to use an unregistered type");
750 // create the struct to hold the object
751 void* obj = lua_newuserdata(L, sizeof(object_rep));
752 assert(obj && "internal error, please report");
753 // we send 0 as destructor since we know it will never be called
754 new(obj) object_rep(const_cast<T*>(ptr), crep, object_rep::constant, 0);
756 // set the meta table
757 detail::getref(L, crep->metatable_ref());
758 lua_setmetatable(L, -2);
763 template<class T> struct make_const_pointer { typedef const T* type; };
764 template<>
765 struct const_pointer_converter<lua_to_cpp>
766 : private pointer_converter<lua_to_cpp>
768 typedef boost::mpl::bool_<false> is_value_converter;
769 typedef const_pointer_converter type;
771 template<class T>
772 typename make_const_pointer<T>::type apply(lua_State* L, by_const_pointer<T>, int index)
774 return pointer_converter<lua_to_cpp>::apply(L, by_pointer<T>(), index);
777 template<class T>
778 static int match(lua_State* L, by_const_pointer<T>, int index)
780 if (lua_isnil(L, index)) return 0;
781 object_rep* obj = is_class_object(L, index);
782 if (obj == 0) return -1; // if the type is not one of our own registered types, classify it as a non-match
784 if ((LUABIND_TYPE_INFO_EQUAL(obj->crep()->holder_type(), LUABIND_TYPEID(T))))
785 return (obj->flags() & object_rep::constant)?-1:0;
786 if ((LUABIND_TYPE_INFO_EQUAL(obj->crep()->const_holder_type(), LUABIND_TYPEID(T))))
787 return (obj->flags() & object_rep::constant)?0:1;
789 bool const_ = obj->flags() & object_rep::constant;
790 int d;
791 int points = implicit_cast(obj->crep(), LUABIND_TYPEID(T), d);
792 return points == -1 ? -1 : points + !const_;
795 template<class T>
796 void converter_postcall(lua_State* L, by_const_pointer<T>, int index)
798 pointer_converter<lua_to_cpp>::converter_postcall(L, by_pointer<T>(), index);
802 // ******* reference converter *******
804 template<class Direction> struct ref_converter;
806 template<>
807 struct ref_converter<cpp_to_lua>
809 typedef boost::mpl::bool_<false> is_value_converter;
810 typedef ref_converter type;
812 template<class T>
813 void apply(lua_State* L, T& ref)
815 if (luabind::get_back_reference(L, ref))
816 return;
818 class_rep* crep = get_class_rep<T>(L);
820 // if you get caught in this assert you are
821 // trying to use an unregistered type
822 assert(crep && "you are trying to use an unregistered type");
824 T* ptr = &ref;
826 // create the struct to hold the object
827 void* obj = lua_newuserdata(L, sizeof(object_rep));
828 assert(obj && "internal error, please report");
829 new(obj) object_rep(ptr, crep, 0, 0);
831 // set the meta table
832 detail::getref(L, crep->metatable_ref());
833 lua_setmetatable(L, -2);
837 template<class T> struct make_reference { typedef T& type; };
838 template<>
839 struct ref_converter<lua_to_cpp>
841 typedef boost::mpl::bool_<false> is_value_converter;
842 typedef ref_converter type;
844 template<class T>
845 typename make_reference<T>::type apply(lua_State* L, by_reference<T>, int index)
847 assert(!lua_isnil(L, index));
848 return *pointer_converter<lua_to_cpp>().apply(L, by_pointer<T>(), index);
851 template<class T>
852 static int match(lua_State* L, by_reference<T>, int index)
854 if (lua_isnil(L, index)) return -1;
855 return pointer_converter<lua_to_cpp>::match(L, by_pointer<T>(), index);
858 template<class T>
859 void converter_postcall(lua_State*, T, int) {}
862 // ******** const reference converter *********
864 template<class Direction> struct const_ref_converter;
866 template<>
867 struct const_ref_converter<cpp_to_lua>
869 typedef boost::mpl::bool_<false> is_value_converter;
870 typedef const_ref_converter type;
872 template<class T>
873 void apply(lua_State* L, T const& ref)
875 if (luabind::get_back_reference(L, ref))
876 return;
878 class_rep* crep = get_class_rep<T>(L);
880 // if you get caught in this assert you are
881 // trying to use an unregistered type
882 assert(crep && "you are trying to use an unregistered type");
884 T const* ptr = &ref;
886 // create the struct to hold the object
887 void* obj = lua_newuserdata(L, sizeof(object_rep));
888 assert(obj && "internal error, please report");
889 new(obj) object_rep(const_cast<T*>(ptr), crep, object_rep::constant, 0);
891 // set the meta table
892 detail::getref(L, crep->metatable_ref());
893 lua_setmetatable(L, -2);
897 template<>
898 struct const_ref_converter<lua_to_cpp>
900 typedef boost::mpl::bool_<false> is_value_converter;
901 typedef const_ref_converter type;
903 // TODO: align!
904 char target[32];
905 void (*destructor)(void*);
907 const_ref_converter(): destructor(0) {}
909 template<class T>
910 typename make_const_reference<T>::type apply(lua_State* L, by_const_reference<T>, int index)
912 object_rep* obj = 0;
913 class_rep const * crep = 0;
915 // special case if we get nil in, try to convert the holder type
916 if (lua_isnil(L, index))
918 crep = get_class_rep<T>(L);
919 assert(crep);
921 else
923 obj = static_cast<object_rep*>(lua_touserdata(L, index));
924 assert((obj != 0) && "internal error, please report"); // internal error
925 crep = obj->crep();
927 assert(crep);
929 T* ptr = reinterpret_cast<T*>(crep->convert_to(LUABIND_TYPEID(T), obj, target));
930 // if the pointer returned points into the converter storage,
931 // we need to destruct it once the converter destructs
932 if ((void*)ptr == (void*)target) destructor = detail::destruct_only_s<T>::apply;
933 assert(!destructor || sizeof(T) <= 32);
935 return *ptr;
938 template<class T>
939 static int match(lua_State* L, by_const_reference<T>, int index)
941 // special case if we get nil in, try to match the holder type
942 if (lua_isnil(L, index))
944 class_rep* crep = get_class_rep<T>(L);
945 if (crep == 0) return -1;
946 if ((LUABIND_TYPE_INFO_EQUAL(crep->holder_type(), LUABIND_TYPEID(T))))
947 return 0;
948 if ((LUABIND_TYPE_INFO_EQUAL(crep->const_holder_type(), LUABIND_TYPEID(T))))
949 return 0;
950 return -1;
953 object_rep* obj = is_class_object(L, index);
954 if (obj == 0) return -1; // if the type is not one of our own registered types, classify it as a non-match
956 if ((LUABIND_TYPE_INFO_EQUAL(obj->crep()->holder_type(), LUABIND_TYPEID(T))))
957 return (obj->flags() & object_rep::constant)?-1:0;
958 if ((LUABIND_TYPE_INFO_EQUAL(obj->crep()->const_holder_type(), LUABIND_TYPEID(T))))
959 return (obj->flags() & object_rep::constant)?0:1;
961 bool const_ = obj->flags() & object_rep::constant;
962 int d;
963 int points = implicit_cast(obj->crep(), LUABIND_TYPEID(T), d);
964 return points == -1 ? -1 : points + !const_;
967 ~const_ref_converter()
969 if (destructor) destructor(target);
972 template<class T>
973 void converter_postcall(lua_State* L, by_const_reference<T>, int index)
978 // ****** enum converter ********
980 template<class Direction = cpp_to_lua>
981 struct enum_converter
983 typedef boost::mpl::bool_<false> is_value_converter;
984 typedef enum_converter type;
986 void apply(lua_State* L, int val)
988 lua_pushnumber(L, val);
992 template<>
993 struct enum_converter<lua_to_cpp>
995 typedef boost::mpl::bool_<false> is_value_converter;
996 typedef enum_converter type;
998 template<class T>
999 T apply(lua_State* L, by_value<T>, int index)
1001 return static_cast<T>(static_cast<int>(lua_tonumber(L, index)));
1004 template<class T>
1005 static int match(lua_State* L, by_value<T>, int index)
1007 if (lua_isnumber(L, index)) return 0; else return -1;
1010 template<class T>
1011 T apply(lua_State* L, by_const_reference<T>, int index)
1013 return static_cast<T>(static_cast<int>(lua_tonumber(L, index)));
1016 template<class T>
1017 static int match(lua_State* L, by_const_reference<T>, int index)
1019 if (lua_isnumber(L, index)) return 0; else return -1;
1022 template<class T>
1023 void converter_postcall(lua_State*, T, int) {}
1026 // ****** functor converter ********
1028 template<class Direction> struct functor_converter;
1030 template<>
1031 struct functor_converter<lua_to_cpp>
1033 typedef functor_converter type;
1035 template<class T>
1036 functor<T> apply(lua_State* L, by_const_reference<functor<T> >, int index)
1038 if (lua_isnil(L, index))
1039 return functor<T>();
1041 lua_pushvalue(L, index);
1042 detail::lua_reference ref;
1043 ref.set(L);
1044 return functor<T>(L, ref);
1047 template<class T>
1048 functor<T> apply(lua_State* L, by_value<functor<T> >, int index)
1050 if (lua_isnil(L, index))
1051 return functor<T>();
1053 lua_pushvalue(L, index);
1054 detail::lua_reference ref;
1055 ref.set(L);
1056 return functor<T>(L, ref);
1059 template<class T>
1060 static int match(lua_State* L, by_const_reference<functor<T> >, int index)
1062 if (lua_isfunction(L, index) || lua_isnil(L, index)) return 0; else return -1;
1065 template<class T>
1066 static int match(lua_State* L, by_value<functor<T> >, int index)
1068 if (lua_isfunction(L, index) || lua_isnil(L, index)) return 0; else return -1;
1071 template<class T>
1072 void converter_postcall(lua_State*, T, int) {}
1076 template<class Direction>
1077 struct value_wrapper_converter;
1079 template<>
1080 struct value_wrapper_converter<lua_to_cpp>
1082 typedef boost::mpl::bool_<false> is_value_converter;
1083 typedef value_wrapper_converter type;
1085 template<class T>
1086 T apply(lua_State* L, by_const_reference<T>, int index)
1088 return T(from_stack(L, index));
1091 template<class T>
1092 T apply(lua_State* L, by_value<T>, int index)
1094 return apply(L, by_const_reference<T>(), index);
1097 template<class T>
1098 static int match(lua_State* L, by_const_reference<T>, int index)
1100 return value_wrapper_traits<T>::check(L, index)
1101 ? (std::numeric_limits<int>::max)() / LUABIND_MAX_ARITY
1102 : -1;
1105 template<class T>
1106 static int match(lua_State* L, by_value<T>, int index)
1108 return match(L, by_const_reference<T>(), index);
1111 void converter_postcall(...) {}
1114 template<>
1115 struct value_wrapper_converter<cpp_to_lua>
1117 typedef boost::mpl::bool_<false> is_value_converter;
1118 typedef value_wrapper_converter type;
1120 template<class T>
1121 void apply(lua_State* interpreter, T const& value_wrapper)
1123 value_wrapper_traits<T>::unwrap(interpreter, value_wrapper);
1127 // *********** default_policy *****************
1129 using boost::mpl::eval_if;
1131 struct default_policy : converter_policy_tag
1133 BOOST_STATIC_CONSTANT(bool, has_arg = true);
1135 template<class T>
1136 static void precall(lua_State*, T, int) {}
1138 template<class T, class Direction>
1139 struct apply
1140 : eval_if<
1141 is_user_defined<T>
1142 , user_defined_converter<Direction>
1143 , eval_if<
1144 is_value_wrapper_arg<T>
1145 , value_wrapper_converter<Direction>
1146 , eval_if<
1147 is_primitive<T>
1148 , primitive_converter<Direction>
1149 , eval_if<
1150 // is_lua_functor<T>
1151 // , functor_converter<Direction>
1152 // , eval_if<
1153 boost::is_enum<typename boost::remove_reference<T>::type>
1154 , enum_converter<Direction>
1155 , eval_if<
1156 is_nonconst_pointer<T>
1157 , pointer_converter<Direction>
1158 , eval_if<
1159 is_const_pointer<T>
1160 , const_pointer_converter<Direction>
1161 , eval_if<
1162 is_nonconst_reference<T>
1163 , ref_converter<Direction>
1164 , eval_if<
1165 is_const_reference<T>
1166 , const_ref_converter<Direction>
1167 , value_converter<Direction>
1173 // >
1181 // ============== new policy system =================
1183 template<int, class> struct find_conversion_policy;
1185 template<bool IsConverter = false>
1186 struct find_conversion_impl
1188 template<int N, class Policies>
1189 struct apply
1191 typedef typename find_conversion_policy<N, typename Policies::tail>::type type;
1195 template<>
1196 struct find_conversion_impl<true>
1198 template<int N, class Policies>
1199 struct apply
1201 typedef typename Policies::head head;
1202 typedef typename Policies::tail tail;
1204 BOOST_STATIC_CONSTANT(bool, found = (N == head::index));
1206 typedef typename
1207 boost::mpl::if_c<found
1208 , head
1209 , typename find_conversion_policy<N, tail>::type
1210 >::type type;
1214 template<class Policies>
1215 struct find_conversion_impl2
1217 template<int N>
1218 struct apply
1219 : find_conversion_impl<
1220 boost::is_base_and_derived<conversion_policy_base, typename Policies::head>::value
1221 >::template apply<N, Policies>
1226 template<>
1227 struct find_conversion_impl2<detail::null_type>
1229 template<int N>
1230 struct apply
1232 typedef default_policy type;
1236 template<int N, class Policies>
1237 struct find_conversion_policy : find_conversion_impl2<Policies>::template apply<N>
1241 template<class List>
1242 struct policy_list_postcall
1244 typedef typename List::head head;
1245 typedef typename List::tail tail;
1247 static void apply(lua_State* L, const index_map& i)
1249 head::postcall(L, i);
1250 policy_list_postcall<tail>::apply(L, i);
1254 template<>
1255 struct policy_list_postcall<detail::null_type>
1257 static void apply(lua_State*, const index_map&) {}
1260 // ==================================================
1262 // ************** precall and postcall on policy_cons *********************
1265 template<class List>
1266 struct policy_precall
1268 typedef typename List::head head;
1269 typedef typename List::tail tail;
1271 static void apply(lua_State* L, int index)
1273 head::precall(L, index);
1274 policy_precall<tail>::apply(L, index);
1278 template<>
1279 struct policy_precall<detail::null_type>
1281 static void apply(lua_State*, int) {}
1284 template<class List>
1285 struct policy_postcall
1287 typedef typename List::head head;
1288 typedef typename List::tail tail;
1290 static void apply(lua_State* L, int index)
1292 head::postcall(L, index);
1293 policy_postcall<tail>::apply(L, index);
1297 template<>
1298 struct policy_postcall<detail::null_type>
1300 static void apply(lua_State*, int) {}
1303 }} // namespace luabind::detail
1306 namespace luabind { namespace
1308 #if defined(__GNUC__) && \
1309 (__GNUC__ * 100 + __GNUC_MINOR__ <= 400 || BOOST_VERSION <= 103401)
1310 static inline boost::arg<0> return_value()
1312 return boost::arg<0>();
1315 static inline boost::arg<0> result()
1317 return boost::arg<0>();
1319 # define LUABIND_PLACEHOLDER_ARG(N) boost::arg<N>(*)()
1320 #elif defined(BOOST_MSVC) || defined(__MWERKS__)
1321 static boost::arg<0> return_value;
1322 static boost::arg<0> result;
1323 # define LUABIND_PLACEHOLDER_ARG(N) boost::arg<N>
1324 #else
1325 boost::arg<0> return_value;
1326 boost::arg<0> result;
1327 # define LUABIND_PLACEHOLDER_ARG(N) boost::arg<N>
1328 #endif
1331 #endif // LUABIND_POLICY_HPP_INCLUDED