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>
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>
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
);
82 index_map(const int* m
): m_map(m
) {}
84 int operator[](int index
) const
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(...);
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;
122 namespace luabind
{ namespace detail
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(...);
134 no_t is_lua_functor_test(const T&);
138 struct is_lua_functor
142 BOOST_STATIC_CONSTANT(bool, value = sizeof(is_lua_functor_test(t)) == sizeof(yes_t));
145 template<class H
, class T
>
152 policy_cons
<U
, policy_cons
<H
,T
> > operator,(policy_cons
<U
,detail::null_type
>)
154 return policy_cons
<U
, policy_cons
<H
,T
> >();
158 policy_cons
<U
, policy_cons
<H
,T
> > operator+(policy_cons
<U
,detail::null_type
>)
160 return policy_cons
<U
, policy_cons
<H
,T
> >();
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
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(...);
182 struct is_policy_cons
186 BOOST_STATIC_CONSTANT(bool, value
=
187 sizeof(is_policy_cons_test(t
)) == sizeof(yes_t
));
189 typedef boost::mpl::bool_
<value
> type
;
193 struct is_string_literal
195 static no_t
helper(indirection_layer
);
196 static yes_t
helper(const char*);
200 struct is_string_literal
<false>
202 static no_t
helper(indirection_layer
);
207 struct is_primitive
/*: boost::mpl::bool_c<false>*/
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> {};
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
;
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
)
285 lua_pushstring(L
, v
);
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
); }
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;
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
;
399 struct user_defined_converter
<lua_to_cpp
>
401 typedef boost::mpl::bool_
<false> is_value_converter
;
402 typedef user_defined_converter type
;
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
);
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
);
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
);
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
);
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
);
440 static int match(lua_State
* L
, T
, int index
)
442 using namespace converters
;
443 return match_lua_to_cpp(L
, T(), index
);
447 void converter_postcall(lua_State
*, T
, int) {}
451 struct user_defined_converter
<cpp_to_lua
>
453 typedef boost::mpl::bool_
<false> is_value_converter
;
454 typedef user_defined_converter type
;
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
;
470 struct pointer_converter
<cpp_to_lua
>
472 typedef boost::mpl::bool_
<false> is_value_converter
;
473 typedef pointer_converter type
;
476 void apply(lua_State
* L
, T
* ptr
)
484 if (luabind::get_back_reference(L
, ptr
))
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
; };
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?!
513 void (*destructor
)(void *);
515 pointer_converter(): destructor(0) {}
518 typename make_pointer
<T
>::type
apply(lua_State
* L
, by_pointer
<T
>, int index
)
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);
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;
554 return implicit_cast(obj
->crep(), LUABIND_TYPEID(T
), d
);
559 if (destructor
) destructor(target
);
563 void converter_postcall(lua_State
*, by_pointer
<T
>, int)
567 // ******* value converter *******
569 template<class Direction
> struct value_converter
;
572 struct value_converter
<cpp_to_lua
>
574 typedef boost::mpl::bool_
<true> is_value_converter
;
575 typedef value_converter type
;
578 void apply(lua_State
* L
, const T
& ref
)
580 if (luabind::get_back_reference(L
, ref
))
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");
592 boost::tie(obj_rep
,held
) = crep
->allocate(L
);
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()))
604 flags
|= object_rep::constant
;
605 destructor
= crep
->const_holder_destructor();
607 else if (LUABIND_TYPE_INFO_EQUAL(LUABIND_TYPEID(T
), crep
->holder_type()))
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());
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
; };
637 struct destruct_guard
641 destruct_guard(T
* p
): ptr(p
), dismiss(false) {}
651 struct value_converter
<lua_to_cpp
>
653 typedef boost::mpl::bool_
<true> is_value_converter
;
654 typedef value_converter type
;
657 T
apply(lua_State
* L
, by_value
<T
>, int index
)
660 // lua_isuserdata(L, index);
661 // getmetatable().__lua_class is true
662 // object_rep->flags() & object_rep::constant == 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
);
675 obj
= static_cast<object_rep
*>(lua_touserdata(L
, index
));
676 assert((obj
!= 0) && "internal error, please report"); // internal error
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;
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
))))
701 if ((LUABIND_TYPE_INFO_EQUAL(crep
->const_holder_type(), LUABIND_TYPEID(T
))))
706 object_rep
* obj
= is_class_object(L
, index
);
707 if (obj
== 0) return -1;
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
);
719 void converter_postcall(lua_State
*, T
, int) {}
722 // ******* const pointer converter *******
724 template<class Direction
> struct const_pointer_converter
;
727 struct const_pointer_converter
<cpp_to_lua
>
729 typedef boost::mpl::bool_
<false> is_value_converter
;
730 typedef const_pointer_converter type
;
733 void apply(lua_State
* L
, const T
* ptr
)
741 if (luabind::get_back_reference(L
, ptr
))
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
; };
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
;
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
);
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
;
791 int points
= implicit_cast(obj
->crep(), LUABIND_TYPEID(T
), d
);
792 return points
== -1 ? -1 : points
+ !const_
;
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
;
807 struct ref_converter
<cpp_to_lua
>
809 typedef boost::mpl::bool_
<false> is_value_converter
;
810 typedef ref_converter type
;
813 void apply(lua_State
* L
, T
& ref
)
815 if (luabind::get_back_reference(L
, ref
))
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");
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
; };
839 struct ref_converter
<lua_to_cpp
>
841 typedef boost::mpl::bool_
<false> is_value_converter
;
842 typedef ref_converter type
;
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
);
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
);
859 void converter_postcall(lua_State
*, T
, int) {}
862 // ******** const reference converter *********
864 template<class Direction
> struct const_ref_converter
;
867 struct const_ref_converter
<cpp_to_lua
>
869 typedef boost::mpl::bool_
<false> is_value_converter
;
870 typedef const_ref_converter type
;
873 void apply(lua_State
* L
, T
const& ref
)
875 if (luabind::get_back_reference(L
, ref
))
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");
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);
898 struct const_ref_converter
<lua_to_cpp
>
900 typedef boost::mpl::bool_
<false> is_value_converter
;
901 typedef const_ref_converter type
;
905 void (*destructor
)(void*);
907 const_ref_converter(): destructor(0) {}
910 typename make_const_reference
<T
>::type
apply(lua_State
* L
, by_const_reference
<T
>, int index
)
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
);
923 obj
= static_cast<object_rep
*>(lua_touserdata(L
, index
));
924 assert((obj
!= 0) && "internal error, please report"); // internal error
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);
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
))))
948 if ((LUABIND_TYPE_INFO_EQUAL(crep
->const_holder_type(), LUABIND_TYPEID(T
))))
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
;
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
);
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
);
993 struct enum_converter
<lua_to_cpp
>
995 typedef boost::mpl::bool_
<false> is_value_converter
;
996 typedef enum_converter type
;
999 T
apply(lua_State
* L
, by_value
<T
>, int index
)
1001 return static_cast<T
>(static_cast<int>(lua_tonumber(L
, index
)));
1005 static int match(lua_State
* L
, by_value
<T
>, int index
)
1007 if (lua_isnumber(L
, index
)) return 0; else return -1;
1011 T
apply(lua_State
* L
, by_const_reference
<T
>, int index
)
1013 return static_cast<T
>(static_cast<int>(lua_tonumber(L
, index
)));
1017 static int match(lua_State
* L
, by_const_reference
<T
>, int index
)
1019 if (lua_isnumber(L
, index
)) return 0; else return -1;
1023 void converter_postcall(lua_State
*, T
, int) {}
1026 // ****** functor converter ********
1028 template<class Direction> struct functor_converter;
1031 struct functor_converter<lua_to_cpp>
1033 typedef functor_converter type;
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;
1044 return functor<T>(L, ref);
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;
1056 return functor<T>(L, ref);
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;
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;
1072 void converter_postcall(lua_State*, T, int) {}
1076 template<class Direction
>
1077 struct value_wrapper_converter
;
1080 struct value_wrapper_converter
<lua_to_cpp
>
1082 typedef boost::mpl::bool_
<false> is_value_converter
;
1083 typedef value_wrapper_converter type
;
1086 T
apply(lua_State
* L
, by_const_reference
<T
>, int index
)
1088 return T(from_stack(L
, index
));
1092 T
apply(lua_State
* L
, by_value
<T
>, int index
)
1094 return apply(L
, by_const_reference
<T
>(), index
);
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
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(...) {}
1115 struct value_wrapper_converter
<cpp_to_lua
>
1117 typedef boost::mpl::bool_
<false> is_value_converter
;
1118 typedef value_wrapper_converter type
;
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);
1136 static void precall(lua_State
*, T
, int) {}
1138 template<class T
, class Direction
>
1142 , user_defined_converter
<Direction
>
1144 is_value_wrapper_arg
<T
>
1145 , value_wrapper_converter
<Direction
>
1148 , primitive_converter
<Direction
>
1150 // is_lua_functor<T>
1151 // , functor_converter<Direction>
1153 boost::is_enum
<typename
boost::remove_reference
<T
>::type
>
1154 , enum_converter
<Direction
>
1156 is_nonconst_pointer
<T
>
1157 , pointer_converter
<Direction
>
1160 , const_pointer_converter
<Direction
>
1162 is_nonconst_reference
<T
>
1163 , ref_converter
<Direction
>
1165 is_const_reference
<T
>
1166 , const_ref_converter
<Direction
>
1167 , value_converter
<Direction
>
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
>
1191 typedef typename find_conversion_policy
<N
, typename
Policies::tail
>::type type
;
1196 struct find_conversion_impl
<true>
1198 template<int N
, class Policies
>
1201 typedef typename
Policies::head head
;
1202 typedef typename
Policies::tail tail
;
1204 BOOST_STATIC_CONSTANT(bool, found
= (N
== head::index
));
1207 boost::mpl::if_c
<found
1209 , typename find_conversion_policy
<N
, tail
>::type
1214 template<class Policies
>
1215 struct find_conversion_impl2
1219 : find_conversion_impl
<
1220 boost::is_base_and_derived
<conversion_policy_base
, typename
Policies::head
>::value
1221 >::template apply
<N
, Policies
>
1227 struct find_conversion_impl2
<detail::null_type
>
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
);
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
);
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
);
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>
1325 boost::arg
<0> return_value
;
1326 boost::arg
<0> result
;
1327 # define LUABIND_PLACEHOLDER_ARG(N) boost::arg<N>
1331 #endif // LUABIND_POLICY_HPP_INCLUDED