*** empty log message ***
[luabind.git] / luabind / class.hpp
blob305b2522dc1ef8732853a88084d71b17bd91ad68
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_CLASS_HPP_INCLUDED
25 #define LUABIND_CLASS_HPP_INCLUDED
28 ISSUES:
29 ------------------------------------------------------
31 * solved for member functions, not application operator *
32 if we have a base class that defines a function a derived class must be able to
33 override that function (not just overload). Right now we just add the other overload
34 to the overloads list and will probably get an ambiguity. If we want to support this
35 each method_rep must include a vector of type_info pointers for each parameter.
36 Operators do not have this problem, since operators always have to have
37 it's own type as one of the arguments, no ambiguity can occur. Application
38 operator, on the other hand, would have this problem.
39 Properties cannot be overloaded, so they should always be overridden.
40 If this is to work for application operator, we really need to specify if an application
41 operator is const or not.
43 If one class registers two functions with the same name and the same
44 signature, there's currently no error. The last registered function will
45 be the one that's used.
46 How do we know which class registered the function? If the function was
47 defined by the base class, it is a legal operation, to override it.
48 we cannot look at the pointer offset, since it always will be zero for one of the bases.
52 TODO:
53 ------------------------------------------------------
55 scopes
56 classes with the same name in different scopes will have the same (fully qualified) name.
57 functions that are renamed will still have the same name in error-messages
59 finish smart pointer support
60 * make sure there are no bugs in the conversion from holder to const_holder
61 * the adopt policy should not be able to adopt pointers to held_types. This
62 must be prohibited.
63 * name_of_type must recognize holder_types and not return "custom"
65 support calling functions on lua threads (i.e. use lua_resume() instead of lua_pcall()).
67 document the new yield-policy more
69 document custom policies, custom converters
71 store the instance object for policies.
73 support the __concat metamethod. This is a bit tricky, since it cannot be
74 treated as a normal operator. It is a binary operator but we want to use the
75 __tostring implementation for both arguments.
79 #include <luabind/prefix.hpp>
80 #include <luabind/config.hpp>
82 #include <string>
83 #include <map>
84 #include <vector>
85 #include <cassert>
87 #include <boost/static_assert.hpp>
88 #include <boost/type_traits.hpp>
89 #include <boost/bind.hpp>
90 #include <boost/function.hpp>
91 #include <boost/preprocessor/repetition/enum_params.hpp>
92 #include <boost/preprocessor/repetition/enum_params_with_a_default.hpp>
93 #include <boost/preprocessor/repetition/repeat.hpp>
94 #include <boost/type_traits/is_same.hpp>
95 #include <boost/mpl/list.hpp>
96 #include <boost/mpl/apply.hpp>
97 #include <boost/mpl/lambda.hpp>
98 #include <boost/mpl/logical.hpp>
99 #include <boost/mpl/find_if.hpp>
100 #include <boost/mpl/apply_if.hpp>
101 #include <boost/mpl/logical.hpp>
103 #include <luabind/config.hpp>
104 #include <luabind/scope.hpp>
105 #include <luabind/detail/constructor.hpp>
106 #include <luabind/detail/call.hpp>
107 #include <luabind/detail/signature_match.hpp>
108 #include <luabind/detail/primitives.hpp>
109 #include <luabind/detail/property.hpp>
110 #include <luabind/detail/typetraits.hpp>
111 #include <luabind/detail/class_rep.hpp>
112 #include <luabind/detail/method_rep.hpp>
113 #include <luabind/detail/construct_rep.hpp>
114 #include <luabind/detail/object_rep.hpp>
115 #include <luabind/detail/operators.hpp>
116 #include <luabind/detail/calc_arity.hpp>
117 #include <luabind/detail/call_member.hpp>
118 #include <luabind/detail/enum_maker.hpp>
119 #include <luabind/detail/get_signature.hpp>
120 #include <luabind/detail/implicit_cast.hpp>
121 #include <luabind/detail/operator_id.hpp>
122 #include <luabind/detail/pointee_typeid.hpp>
124 //#include <boost/langbinding/inheritance.hpp>
126 namespace luabind
128 namespace detail
130 struct unspecified {};
133 using detail::type;
135 template<class T, class X1 = detail::unspecified, class X2 = detail::unspecified, class X3 = detail::unspecified>
136 struct class_;
138 // TODO: this function will only be invoked if the user hasn't defined a correct overload
139 // maybe we should have a static assert in here?
140 inline detail::null_type* get_const_holder(...)
142 return 0;
145 namespace detail
147 template<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_BASES, class A)>
148 double is_bases_helper(const bases<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_BASES, A)>&);
150 #ifndef BOOST_MSVC
151 template<class T>
152 char is_bases_helper(const T&);
153 #else
154 char is_bases_helper(...);
155 #endif
157 template<class T>
158 struct is_bases
160 static const T& t;
162 BOOST_STATIC_CONSTANT(bool, value = sizeof(is_bases_helper(t)) == sizeof(double));
163 typedef boost::mpl::bool_<value> type;
164 BOOST_MPL_AUX_LAMBDA_SUPPORT(1,is_bases,(T))
167 double is_not_unspecified_helper(const unspecified*);
168 char is_not_unspecified_helper(...);
170 template<class T>
171 struct is_not_unspecified
173 BOOST_STATIC_CONSTANT(bool, value = sizeof(is_not_unspecified_helper(static_cast<T*>(0))) == sizeof(char));
174 typedef boost::mpl::bool_<value> type;
175 BOOST_MPL_AUX_LAMBDA_SUPPORT(1,is_not_unspecified,(T))
178 template<class Predicate>
179 struct get_predicate
181 typedef typename boost::mpl::and_<
182 Predicate
183 , is_not_unspecified<boost::mpl::_1>
184 > type;
187 template<class Parameters, class Predicate, class DefaultValue>
188 struct extract_parameter
190 typedef typename get_predicate<Predicate>::type pred;
191 typedef typename boost::mpl::find_if<Parameters, pred>::type iterator;
192 typedef typename boost::mpl::apply_if<boost::is_same<iterator, typename boost::mpl::end<Parameters>::type>
193 , boost::mpl::identity<DefaultValue>
194 , iterator
195 >::type type;
198 // this should know about the smart pointer type.
199 // and should really do:
200 // get_pointer(*static_cast<SmartPointer*>(obj_ptr))
201 // to extract the held pointer.
202 template<class HeldType, class T, class F, class Policies>
203 struct function_callback_non_null : Policies
205 function_callback_non_null(F f_): f(f_) {}
206 inline int operator()(lua_State* L, void* obj_ptr)
208 // HeldType& held_obj = *static_cast<HeldType*>(obj_ptr);
209 // T* ptr = static_cast<T*>(luabind::get_pointer(held_obj));
210 // is this correct?
211 T* ptr = static_cast<T*>(obj_ptr);
213 return call(f, ptr, L, static_cast<Policies*>(this));
215 F f;
218 template<class T, class F, class Policies>
219 struct function_callback_null_type : Policies
221 function_callback_null_type(F f_): f(f_) {}
222 inline int operator()(lua_State* L, void* obj_ptr)
224 // std::cout << "HeldType: null_type\n";
225 T* ptr = static_cast<T*>(obj_ptr);
226 return call(f, ptr, L, static_cast<Policies*>(this));
228 F f;
231 template<class HeldType, class T, class F, class Policies>
232 struct function_callback_s
234 typedef typename
235 boost::mpl::if_<boost::is_same<HeldType,detail::null_type>
236 , function_callback_null_type<T,F,Policies>
237 , function_callback_non_null<HeldType,T,F,Policies>
238 >::type type;
241 template<class T, class F, class Policies>
242 struct match_function_callback_s
244 static inline int apply(lua_State* L)
246 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, 1));
247 F fptr = 0;
248 return match(fptr, L, obj->flags() & object_rep::constant, static_cast<Policies*>(0));
252 // prints the types of the values on the stack, in the
253 // range [start_index, lua_gettop()]
255 LUABIND_API std::string stack_content_by_name(lua_State* L, int start_index);
257 struct LUABIND_API create_class
259 static int stage1(lua_State* L);
260 static int stage2(lua_State* L);
263 template<class Type>
264 struct register_wrapped_type
266 template<class Signature, class Policies>
267 static void apply(detail::construct_rep::overload_t& o, const Signature*, const Policies*)
269 o.set_wrapped_constructor(
270 &detail::construct_wrapped_class<Type, Policies, Signature>::apply
275 template<>
276 struct register_wrapped_type<detail::null_type>
278 template<class Signature, class Policies>
279 static void apply(detail::construct_rep::overload_t&, const Signature*, const Policies*) {}
283 // if the class is held by a smart pointer, we need to be able to
284 // implicitly dereference the pointer when needed.
286 template<class UnderlyingT, class HeldT>
287 struct extract_underlying_type
289 static void* extract(void* ptr)
291 HeldT& held_obj = *reinterpret_cast<HeldT*>(ptr);
292 UnderlyingT* underlying_ptr = static_cast<UnderlyingT*>(get_pointer(held_obj));
293 return underlying_ptr;
297 template<class UnderlyingT, class HeldT>
298 struct extract_underlying_const_type
300 static const void* extract(void* ptr)
302 HeldT& held_obj = *reinterpret_cast<HeldT*>(ptr);
303 const UnderlyingT* underlying_ptr = static_cast<const UnderlyingT*>(get_pointer(held_obj));
304 return underlying_ptr;
308 template<class HeldType>
309 struct internal_holder_extractor
311 typedef void*(*extractor_fun)(void*);
313 template<class T>
314 static extractor_fun apply(detail::type<T>)
316 return &detail::extract_underlying_type<T, HeldType>::extract;
320 template<>
321 struct internal_holder_extractor<detail::null_type>
323 typedef void*(*extractor_fun)(void*);
325 template<class T>
326 static extractor_fun apply(detail::type<T>)
328 return 0;
333 template<class HeldType, class ConstHolderType>
334 struct convert_holder
336 static void apply(void* holder, void* target)
338 new(target) ConstHolderType(*reinterpret_cast<HeldType*>(holder));
343 template<class HeldType>
344 struct const_converter
346 typedef void(*converter_fun)(void*, void*);
348 template<class ConstHolderType>
349 static converter_fun apply(ConstHolderType*)
351 return &detail::convert_holder<HeldType, ConstHolderType>::apply;
355 template<>
356 struct const_converter<detail::null_type>
358 typedef void(*converter_fun)(void*, void*);
360 template<class T>
361 static converter_fun apply(T*)
363 return 0;
370 template<class HeldType>
371 struct internal_const_holder_extractor
373 typedef const void*(*extractor_fun)(void*);
375 template<class T>
376 static extractor_fun apply(detail::type<T>)
378 return get_extractor(detail::type<T>(), luabind::get_const_holder(static_cast<HeldType*>(0)));
380 private:
381 template<class T, class ConstHolderType>
382 static extractor_fun get_extractor(detail::type<T>, ConstHolderType*)
384 return &detail::extract_underlying_const_type<T, ConstHolderType>::extract;
388 template<>
389 struct internal_const_holder_extractor<detail::null_type>
391 typedef const void*(*extractor_fun)(void*);
393 template<class T>
394 static extractor_fun apply(detail::type<T>)
396 return 0;
402 // this is simply a selector that returns the type_info
403 // of the held type, or invalid_type_info if we don't have
404 // a held_type
405 template<class HeldType>
406 struct internal_holder_type
408 static LUABIND_TYPE_INFO apply()
410 return LUABIND_TYPEID(HeldType);
414 template<>
415 struct internal_holder_type<detail::null_type>
417 static LUABIND_TYPE_INFO apply()
419 return LUABIND_INVALID_TYPE_INFO;
424 // this is the actual held_type constructor
425 template<class HeldType, class T>
426 struct internal_construct_holder
428 static void apply(void* target, void* raw_pointer)
430 new(target) HeldType(static_cast<T*>(raw_pointer));
434 // the following two functions are the ones that returns
435 // a pointer to a held_type_constructor, or 0 if there
436 // is no held_type
437 template<class HeldType>
438 struct holder_constructor
440 typedef void(*constructor)(void*,void*);
441 template<class T>
442 static constructor apply(detail::type<T>)
444 return &internal_construct_holder<HeldType, T>::apply;
448 template<>
449 struct holder_constructor<detail::null_type>
451 typedef void(*constructor)(void*,void*);
452 template<class T>
453 static constructor apply(detail::type<T>)
455 return 0;
459 // the following two functions are the ones that returns
460 // a pointer to a const_held_type_constructor, or 0 if there
461 // is no held_type
462 template<class HolderType>
463 struct const_holder_constructor
465 typedef void(*constructor)(void*,void*);
466 template<class T>
467 static constructor apply(detail::type<T>)
469 return get_const_holder_constructor(detail::type<T>(), luabind::get_const_holder(static_cast<HolderType*>(0)));
472 private:
474 template<class T, class ConstHolderType>
475 static constructor get_const_holder_constructor(detail::type<T>, ConstHolderType*)
477 return &internal_construct_holder<ConstHolderType, T>::apply;
481 template<>
482 struct const_holder_constructor<detail::null_type>
484 typedef void(*constructor)(void*,void*);
485 template<class T>
486 static constructor apply(detail::type<T>)
488 return 0;
494 // this is a selector that returns the size of the held_type
495 // or 0 if we don't have a held_type
496 template <class HolderType>
497 struct internal_holder_size
499 static int apply() { return get_internal_holder_size(luabind::get_const_holder(static_cast<HolderType*>(0))); }
500 private:
501 template<class ConstHolderType>
502 static int get_internal_holder_size(ConstHolderType*)
504 return max_c<sizeof(HolderType), sizeof(ConstHolderType)>::value;
508 template <>
509 struct internal_holder_size<detail::null_type>
511 static int apply() { return 0; }
515 // if we have a held type, return the destructor to it
516 // note the difference. The held_type should only be destructed (not deleted)
517 // since it's constructed in the lua userdata
518 template<class HeldType>
519 struct internal_holder_destructor
521 typedef void(*destructor_t)(void*);
522 template<class T>
523 static destructor_t apply(detail::type<T>)
525 return &detail::destruct_only_s<HeldType>::apply;
529 // if we don't have a held type, return the destructor of the raw type
530 template<>
531 struct internal_holder_destructor<detail::null_type>
533 typedef void(*destructor_t)(void*);
534 template<class T>
535 static destructor_t apply(detail::type<T>)
537 return &detail::delete_s<T>::apply;
542 // if we have a held type, return the destructor to it's const version
543 template<class HolderType>
544 struct internal_const_holder_destructor
546 typedef void(*destructor_t)(void*);
547 template<class T>
548 static destructor_t apply(detail::type<T>)
550 return const_holder_type_destructor(luabind::get_const_holder(static_cast<HolderType*>(0)));
553 private:
555 template<class ConstHolderType>
556 static destructor_t const_holder_type_destructor(ConstHolderType*)
558 return &detail::destruct_only_s<ConstHolderType>::apply;
563 // if we don't have a held type, return the destructor of the raw type
564 template<>
565 struct internal_const_holder_destructor<detail::null_type>
567 typedef void(*destructor_t)(void*);
568 template<class T>
569 static destructor_t apply(detail::type<T>)
571 return 0;
578 template<class HolderType>
579 struct get_holder_alignment
581 static int apply()
583 return internal_alignment(luabind::get_const_holder(static_cast<HolderType*>(0)));
586 private:
588 template<class ConstHolderType>
589 static int internal_alignment(ConstHolderType*)
591 return detail::max_c<boost::alignment_of<HolderType>::value
592 , boost::alignment_of<ConstHolderType>::value>::value;
596 template<>
597 struct get_holder_alignment<detail::null_type>
599 static int apply()
601 return 1;
606 } // detail
621 struct class_base: detail::scoped_object
623 protected:
625 struct base_desc
627 LUABIND_TYPE_INFO type;
628 int ptr_offset;
631 private:
633 #ifndef NDEBUG
634 bool m_cloned;
635 #endif
637 const char* m_name;
639 std::map<const char*, detail::method_rep, detail::ltstr> m_methods;
641 // datamembers, some members may be readonly, and
642 // only have a getter function
643 std::map<const char*, detail::class_rep::callback, detail::ltstr> m_getters;
644 std::map<const char*, detail::class_rep::callback, detail::ltstr> m_setters;
646 // the operators in lua
647 std::vector<detail::class_rep::operator_callback> m_operators[detail::number_of_operators];
648 std::map<const char*, int, detail::ltstr> m_static_constants;
650 std::vector<base_desc> m_bases;
651 detail::construct_rep m_constructor;
653 void(*m_destructor)(void*);
654 void(*m_const_holder_destructor)(void*);
656 void*(*m_extractor)(void*);
657 const void*(*m_const_extractor)(void*);
659 void(*m_const_converter)(void*,void*);
661 void(*m_construct_holder)(void*, void*);
662 void(*m_construct_const_holder)(void*, void*);
664 int m_holder_size;
665 int m_holder_alignment;
667 LUABIND_TYPE_INFO m_type;
668 LUABIND_TYPE_INFO m_holder_type;
669 LUABIND_TYPE_INFO m_const_holder_type;
671 #ifndef LUABIND_DONT_COPY_STRINGS
672 // the maps that contains char pointers points into
673 // this vector of strings.
674 std::vector<char*> m_strings;
675 #endif
678 public:
680 // public 'cause of enum_maker, FIX
681 void add_static_constant(const char* name, int val)
683 m_static_constants[name] = val;
686 protected:
688 mutable std::vector<detail::scoped_object*> m_children;
690 void init(LUABIND_TYPE_INFO type
691 , LUABIND_TYPE_INFO holder_type
692 , void*(*extractor)(void*)
693 , const void*(*const_extractor)(void*)
694 , void(*const_converter)(void*,void*)
695 , void(*holder_constructor)(void*,void*)
696 , void(*const_holder_constructor)(void*,void*)
697 , void(*destructor)(void*)
698 , void(*const_holder_destructor)(void*)
699 , int holder_size
700 , int holder_alignment)
702 m_type = type;
703 m_holder_type = holder_type;
704 m_extractor = extractor;
705 m_const_extractor = const_extractor;
706 m_const_converter = const_converter;
707 m_construct_holder = holder_constructor;
708 m_construct_const_holder = const_holder_constructor;
709 m_destructor = destructor;
710 m_const_holder_destructor = const_holder_destructor;
711 m_holder_size = holder_size;
712 m_holder_alignment = holder_alignment;
715 template<class T>
716 void set_const_holder_type(T*)
718 m_const_holder_type = LUABIND_TYPEID(T);
721 inline void add_getter(const char* name, const boost::function2<int, lua_State*, int>& g)
723 detail::class_rep::callback c;
724 c.func = g;
725 c.pointer_offset = 0;
726 #ifndef LUABIND_DONT_COPY_STRINGS
727 m_strings.push_back(detail::dup_string(name));
728 m_getters[m_strings.back()] = c;
729 #else
730 m_getters[name] = c;
731 #endif
734 inline void add_setter(const char* name, const boost::function2<int, lua_State*, int>& s)
736 detail::class_rep::callback c;
737 c.func = s;
738 c.pointer_offset = 0;
739 #ifndef LUABIND_DONT_COPY_STRINGS
740 m_strings.push_back(detail::dup_string(name));
741 m_setters[m_strings.back()] = c;
742 #else
743 m_setters[name] = c;
744 #endif
747 void add_base(const base_desc& b)
749 m_bases.push_back(b);
752 public:
754 void add_constructor(const detail::construct_rep::overload_t& o)
756 m_constructor.overloads.push_back(o);
759 void add_method(const char* name, const detail::overload_rep& o)
761 #ifdef LUABIND_DONT_COPY_STRINGS
762 detail::method_rep& method = m_methods[name];
763 method.name = name;
764 #else
765 m_strings.push_back(detail::dup_string(name));
766 detail::method_rep& method = m_methods[m_strings.back()];
767 method.name = m_strings.back();
768 #endif
769 method.add_overload(o);
770 method.crep = 0;
773 #ifndef LUABIND_NO_ERROR_CHECKING
774 inline void add_operator(int op_id, int(*func)(lua_State*), int(*matcher)(lua_State*), void(*sig)(lua_State*, std::string&), int arity)
775 #else
776 inline void add_operator(int op_id, int(*func)(lua_State*), int(*matcher)(lua_State*), int arity)
777 #endif
779 detail::class_rep::operator_callback o;
780 o.set_fun(func);
781 o.set_match_fun(matcher);
782 o.set_arity(arity);
784 #ifndef LUABIND_NO_ERROR_CHECKING
786 o.set_sig_fun(sig);
788 #endif
789 m_operators[op_id].push_back(o);
798 const char* name() const { return m_name; }
800 class_base(const char* name)
802 #ifndef LUABIND_DONT_COPY_STRINGS
803 m_strings.push_back(detail::dup_string(name));
804 m_name = m_strings.back();
805 #else
806 m_name = name;
807 #endif
809 #ifndef NDEBUG
810 m_cloned = false;
811 #endif
814 virtual ~class_base()
816 for (std::vector<detail::scoped_object*>::iterator
817 i = m_children.begin(); i != m_children.end(); ++i)
818 delete *i;
820 // if we are copying strings, we have to destroy them too
821 #ifndef LUABIND_DONT_COPY_STRINGS
822 for (std::vector<char*>::iterator i = m_strings.begin(); i != m_strings.end(); ++i)
823 delete[] *i;
824 #endif
827 // pushes the class_rep on the lua stack
828 virtual void commit(lua_State* L)
830 assert(!m_cloned && "class already commited");
832 detail::getref(L, scope_stack::top(L));
833 lua_pushstring(L, m_name);
835 detail::class_rep* crep;
837 detail::class_registry* r = detail::class_registry::get_registry(L);
838 // create a class_rep structure for this class.
839 // allocate it within lua to let lua collect it on
840 // lua_close(). This is better than allocating it
841 // as a static, since it will then be destructed
842 // when the program exits instead.
843 // warning: we assume that lua will not
844 // move the userdata memory.
845 lua_newuserdata(L, sizeof(detail::class_rep));
846 crep = reinterpret_cast<detail::class_rep*>(lua_touserdata(L, -1));
848 new(crep) detail::class_rep( m_type
849 , m_name
851 , m_destructor
852 , m_const_holder_destructor
853 , m_holder_type
854 , m_const_holder_type
855 , m_extractor
856 , m_const_extractor
857 , m_const_converter
858 , m_construct_holder
859 , m_construct_const_holder
860 , m_holder_size
861 , m_holder_alignment);
863 // register this new type in the class registry
864 r->add_class(m_type, crep);
865 if (!(LUABIND_TYPE_INFO_EQUAL(m_holder_type, LUABIND_INVALID_TYPE_INFO)))
867 // if we have a held type
868 // we have to register it in the class-table
869 // but only for the base class, if it already
870 // exists, we don't have to register it
871 detail::class_rep* c = r->find_class(m_holder_type);
872 if (c == 0)
874 r->add_class(m_holder_type, crep);
875 r->add_class(m_const_holder_type, crep);
879 // constructors
880 m_constructor.swap(crep->m_constructor);
882 #ifndef LUABIND_DONT_COPY_STRINGS
883 assert(crep->m_strings.empty() && "Internal error");
884 std::swap(crep->m_strings, m_strings);
885 #endif
887 std::swap(crep->m_getters, m_getters);
888 std::swap(crep->m_setters, m_setters);
890 for(int i = 0; i < detail::number_of_operators; ++i)
891 std::swap(crep->m_operators[i], m_operators[i]);
893 std::swap(crep->m_static_constants, m_static_constants);
895 // here!
896 // crep->m_methods = m_methods;
898 for (std::vector<base_desc>::iterator i = m_bases.begin();
899 i != m_bases.end();
900 ++i)
902 detail::class_registry* r = detail::class_registry::get_registry(L);
904 // the baseclass' class_rep structure
905 detail::class_rep* bcrep = r->find_class(i->type);
907 detail::class_rep::base_info base;
908 base.pointer_offset = i->ptr_offset;
909 base.base = bcrep;
911 crep->add_base_class(base);
913 typedef std::map<const char*, detail::method_rep, detail::ltstr> methods_t;
915 for (methods_t::const_iterator i
916 = bcrep->m_methods.begin()
917 ; i != bcrep->m_methods.end()
918 ; ++i)
920 detail::method_rep& m = m_methods[i->first];
922 typedef std::vector<detail::overload_rep> overloads_t;
924 for (overloads_t::const_iterator j
925 = i->second.overloads().begin()
926 ; j != i->second.overloads().end()
927 ; ++j)
929 detail::overload_rep o = *j;
930 o.add_offset(base.pointer_offset);
931 m.add_overload(o);
935 // copy base class table
936 detail::getref(L, crep->table_ref());
937 detail::getref(L, bcrep->table_ref());
938 lua_pushnil(L);
940 while (lua_next(L, -2))
942 lua_pushvalue(L, -2); // copy key
943 lua_insert(L, -2);
944 lua_settable(L, -5);
947 lua_pop(L, 2);
950 crep->m_methods = m_methods;
952 for (std::map<const char*, detail::method_rep, detail::ltstr>::iterator i
953 = crep->m_methods.begin(); i != crep->m_methods.end(); ++i)
955 i->second.crep = crep;
958 // add methods
959 for (std::map<const char*, detail::method_rep, detail::ltstr>::iterator i
960 = m_methods.begin(); i != m_methods.end(); ++i)
962 detail::getref(L, crep->table_ref());
963 lua_pushstring(L, i->first);
964 lua_pushnil(L);
965 lua_settable(L, -3);
966 lua_pop(L, 1);
968 crep->add_method(L, i->first, crep->m_methods[i->first]);
969 i->second.crep = crep;
972 m_methods.clear();
974 lua_settable(L, -3);
975 lua_pop(L, 1);
979 // destructive copy
980 virtual luabind::detail::scoped_object* clone()
982 assert(m_cloned == false);
984 #ifndef NDEBUG
985 m_cloned = true;
986 #endif
988 class_base* ret = new class_base(m_name);
990 std::swap(ret->m_getters, m_getters);
991 std::swap(ret->m_setters, m_setters);
993 for(int i = 0; i < detail::number_of_operators; ++i)
994 std::swap(ret->m_operators[i], m_operators[i]);
996 std::swap(ret->m_static_constants, m_static_constants);
998 ret->init(m_type
999 , m_holder_type
1000 , m_extractor
1001 , m_const_extractor
1002 , m_const_converter
1003 , m_construct_holder
1004 , m_construct_const_holder
1005 , m_destructor
1006 , m_const_holder_destructor
1007 , m_holder_size
1008 , m_holder_alignment);
1010 ret->m_const_holder_type = m_const_holder_type;
1012 ret->m_bases.swap(m_bases);
1013 ret->m_methods.swap(m_methods);
1014 m_constructor.swap(ret->m_constructor);
1016 ret->m_name = m_name;
1018 #ifndef LUABIND_DONT_COPY_STRINGS
1019 std::swap(ret->m_strings, m_strings);
1020 #endif
1022 m_children.swap(ret->m_children);
1024 return ret;
1028 namespace detail {
1030 struct class_registration;
1032 struct class_base : detail::scope
1034 public:
1035 class_base(char const* name);
1037 struct base_desc
1039 LUABIND_TYPE_INFO type;
1040 int ptr_offset;
1043 void init(
1044 LUABIND_TYPE_INFO type
1045 , LUABIND_TYPE_INFO holder_type
1046 , LUABIND_TYPE_INFO const_holder_type
1047 , void*(*extractor)(void*)
1048 , const void*(*const_extractor)(void*)
1049 , void(*const_converter)(void*,void*)
1050 , void(*holder_constructor)(void*,void*)
1051 , void(*const_holder_constructor)(void*,void*)
1052 , void(*destructor)(void*)
1053 , void(*const_holder_destructor)(void*)
1054 , int holder_size
1055 , int holder_alignment);
1057 void add_getter(
1058 const char* name
1059 , const boost::function2<int, lua_State*, int>& g);
1061 #ifdef LUABIND_NO_ERROR_CHECKING
1062 void class_base::add_setter(
1063 const char* name
1064 , const boost::function2<int, lua_State*, int>& s);
1065 #else
1066 void class_base::add_setter(
1067 const char* name
1068 , const boost::function2<int, lua_State*, int>& s
1069 , int (*match)(lua_State*, int)
1070 , void (*get_sig_ptr)(lua_State*, std::string&));
1071 #endif
1073 void add_base(const base_desc& b);
1074 void add_constructor(const detail::construct_rep::overload_t& o);
1075 void add_method(const char* name, const detail::overload_rep& o);
1077 #ifndef LUABIND_NO_ERROR_CHECKING
1078 void add_operator(
1079 int op_id
1080 , int(*func)(lua_State*)
1081 , int(*matcher)(lua_State*)
1082 , void(*sig)(lua_State*
1083 , std::string&)
1084 , int arity);
1085 #else
1086 void add_operator(
1087 int op_id
1088 , int(*func)(lua_State*)
1089 , int(*matcher)(lua_State*)
1090 , int arity);
1091 #endif
1093 const char* name() const;
1095 void add_static_constant(const char* name, int val);
1096 void add_inner_scope(scope& s);
1098 private:
1099 class_registration* m_registration;
1102 } // namespace detail
1104 // registers a class in the lua environment
1105 template<class T, class X1, class X2, class X3>
1106 struct class_: detail::class_base
1108 typedef class_<T, X1, X2, X3> self_t;
1110 private:
1112 template<class A, class B, class C, class D>
1113 class_(const class_<A,B,C,D>&);
1115 public:
1117 // WrappedType MUST inherit from T
1118 typedef typename detail::extract_parameter<
1119 boost::mpl::vector3<X1,X2,X3>
1120 , boost::is_base_and_derived<T, boost::mpl::_>
1121 /* , boost::mpl::not_<
1122 boost::mpl::or_<
1123 detail::is_bases<boost::mpl::_>
1124 , boost::is_base_and_derived<boost::mpl::_, T>
1127 , detail::null_type
1128 >::type WrappedType;
1130 typedef typename detail::extract_parameter<
1131 boost::mpl::list3<X1,X2,X3>
1132 , boost::mpl::not_<
1133 boost::mpl::or_<
1134 boost::mpl::or_<
1135 detail::is_bases<boost::mpl::_>
1136 , boost::is_base_and_derived<boost::mpl::_, T>
1138 , boost::is_base_and_derived<T, boost::mpl::_>
1141 , detail::null_type
1142 >::type HeldType;
1144 template<class To>
1145 void register_downcast(boost::mpl::true_, detail::type<To>* = 0)
1146 { boost::langbinding::register_conversion<To, T>(true); }
1148 template<class To>
1149 void register_downcast(boost::mpl::false_, detail::type<To>* = 0)
1152 // this function generates conversion information
1153 // in the given class_rep structure. It will be able
1154 // to implicitly cast to the given template type
1155 template<class To>
1156 void gen_base_info(detail::type<To>)
1158 // boost::langbinding::register_dynamic_id<To>();
1159 // boost::langbinding::register_conversion<T, To>(false);
1161 // register_downcast<To>(boost::mpl::bool_<boost::is_polymorphic<To>::value>());
1163 // fist, make sure the given base class is registered.
1164 // if it's not registered we can't push it's lua table onto
1165 // the stack because it doesn't have a table
1167 // try to cast this type to the base type and remember
1168 // the pointer offset. For multiple inheritance the pointer
1169 // may change when casting. Since we need to be able to
1170 // cast we need this pointer offset.
1171 // store the information in this class' base class-vector
1172 base_desc base;
1173 base.type = LUABIND_TYPEID(To);
1174 base.ptr_offset = detail::ptr_offset(detail::type<T>(), detail::type<To>());
1175 add_base(base);
1178 void gen_base_info(detail::type<detail::null_type>)
1181 #define LUABIND_GEN_BASE_INFO(z, n, text) gen_base_info(detail::type<B##n>());
1183 template<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_BASES, class B)>
1184 void generate_baseclass_list(detail::type<bases<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_BASES, B)> >)
1186 BOOST_PP_REPEAT(LUABIND_MAX_BASES, LUABIND_GEN_BASE_INFO, _)
1189 #undef LUABIND_GEN_BASE_INFO
1191 // this is the internal version of def() it is run from both overloads
1192 // of def. It has two versions, one where a contstructor is registered
1193 // and one where a function is registered
1194 template<class Policies>
1195 struct internal_def_s
1197 template<class F>
1198 static void apply(const char* name, F f, detail::class_base* c)
1200 // std::cout << "HeldType2: " << typeid(HeldType).name() << "\n";
1202 detail::overload_rep o(f, static_cast<Policies*>(0));
1204 typedef LUABIND_MSVC_TYPENAME detail::function_callback_s<HeldType,T,F,Policies>::type call_t;
1206 o.set_match_fun(&detail::match_function_callback_s<T,F,Policies>::apply);
1207 o.call_fun = boost::bind<int>(call_t(f), _1, _2);
1209 #ifndef LUABIND_NO_ERROR_CHECKING
1211 o.set_sig_fun(&detail::get_member_signature<F>::apply);
1213 #endif
1215 c->add_method(name, o);
1218 template<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, class A)>
1219 static void apply(constructor<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, A)>, detail::class_base* c)
1221 // std::cout << "HeldType2: " << typeid(HeldType).name() << "\n";
1223 detail::construct_rep::overload_t o;
1225 o.set_constructor(
1226 &detail::construct_class<
1228 ,Policies
1229 ,constructor<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, A)>
1230 >::apply
1233 // if we have a WrappedType, we have to register it's constructor
1234 // but if it's null_type (no WrappedType) we should not register it
1235 detail::register_wrapped_type<WrappedType>::apply(o,
1236 static_cast<const constructor<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, A)>*>(0),
1237 static_cast<const Policies*>(0));
1240 o.set_match_fun(
1241 &detail::constructor_match<
1242 constructor<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, A)>
1244 ,Policies
1245 >::apply);
1247 #ifndef LUABIND_NO_ERROR_CHECKING
1249 o.set_sig_fun(&detail::get_signature<constructor<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, A)> >::apply);
1251 #endif
1253 typedef constructor<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, A)> con_t;
1255 o.set_arity(detail::calc_arity<con_t::arity>::apply(con_t(), static_cast<Policies*>(0)));
1257 c->add_constructor(o);
1261 class_(const char* name): class_base(name) { init(); }
1263 template<class F>
1264 class_& def(const char* name, F f)
1266 internal_def_s<detail::null_type>::apply(name, f, this);
1267 return *this;
1270 template<class F, class Policies>
1271 class_& def(const char* name, F f, const Policies&)
1273 internal_def_s<Policies>::apply(name, f, this);
1274 return *this;
1277 template<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, class A)>
1278 class_& def(constructor<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, A)> sig)
1280 internal_def_s<detail::null_type>::apply(sig, this);
1281 return *this;
1284 template<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, class A), class Policies>
1285 class_& def(constructor<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, A)> sig, const Policies& policies)
1287 internal_def_s<Policies>::apply(sig, this);
1288 return *this;
1291 template<class Getter>
1292 class_& property(const char* name, Getter g)
1294 add_getter(name, boost::bind<int>(detail::get_caller<T, Getter, detail::null_type>(), _1, _2, g));
1295 return *this;
1298 template<class Getter, class MaybeSetter>
1299 class_& property(const char* name, Getter g, MaybeSetter s)
1301 return property_impl(name, g, s, boost::mpl::bool_<detail::is_policy_cons<MaybeSetter>::value>());
1304 template<class Getter, class Setter, class GetPolicies>
1305 class_& property(const char* name, Getter g, Setter s, const GetPolicies& get_policies)
1307 add_getter(name, boost::bind<int>(detail::get_caller<T, Getter, GetPolicies>(get_policies), _1, _2, g));
1308 #ifndef LUABIND_NO_ERROR_CHECKING
1309 add_setter(
1310 name
1311 , boost::bind<int>(detail::set_caller<T, Setter, detail::null_type>(), _1, _2, s)
1312 , detail::gen_set_matcher((Setter)0, (detail::null_type*)0)
1313 , &detail::get_member_signature<Setter>::apply);
1314 #else
1315 add_setter(
1316 name
1317 , boost::bind<int>(detail::set_caller<T, Setter, detail::null_type>(), _1, _2, s));
1318 #endif
1319 return *this;
1322 template<class Getter, class Setter, class GetPolicies, class SetPolicies>
1323 class_& property(const char* name
1324 , Getter g, Setter s
1325 , const GetPolicies& get_policies
1326 , const SetPolicies& set_policies)
1328 add_getter(name, boost::bind<int>(detail::get_caller<T, Getter, GetPolicies>(get_policies), _1, _2, g));
1329 #ifndef LUABIND_NO_ERROR_CHECKING
1330 add_setter(
1331 name
1332 , boost::bind<int>(detail::set_caller<T, Setter, SetPolicies>(), _1, _2, s)
1333 , detail::gen_set_matcher((Setter)0, (SetPolicies*)0)
1334 , &detail::get_member_signature<Setter>::apply);
1335 #else
1336 add_setter(name, boost::bind<int>(detail::set_caller<T, Setter, SetPolicies>(set_policies), _1, _2, s));
1337 #endif
1338 return *this;
1341 template<class D>
1342 class_& def_readonly(const char* name, D T::*member_ptr)
1344 add_getter(name, boost::bind<int>(detail::auto_get<T,D,detail::null_type>(), _1, _2, member_ptr));
1345 return *this;
1348 template<class D, class Policies>
1349 class_& def_readonly(const char* name, D T::*member_ptr, const Policies& policies)
1351 add_getter(name, boost::bind<int>(detail::auto_get<T,D,Policies>(policies), _1, _2, member_ptr));
1352 return *this;
1355 template<class D>
1356 class_& def_readwrite(const char* name, D T::*member_ptr)
1358 add_getter(name, boost::bind<int>(detail::auto_get<T,D,detail::null_type>(), _1, _2, member_ptr));
1359 #ifndef LUABIND_NO_ERROR_CHECKING
1360 add_setter(
1361 name
1362 , boost::bind<int>(detail::auto_set<T,D,detail::null_type>(), _1, _2, member_ptr)
1363 , &detail::set_matcher<D, detail::null_type>::apply
1364 , &detail::get_setter_signature<D>::apply);
1365 #else
1366 add_setter(name, boost::bind<int>(detail::auto_set<T,D,detail::null_type>(), _1, _2, member_ptr));
1367 #endif
1368 return *this;
1371 template<class D, class GetPolicies>
1372 class_& def_readwrite(const char* name, D T::*member_ptr, const GetPolicies& get_policies)
1374 add_getter(name, boost::bind<int>(detail::auto_get<T,D,GetPolicies>(get_policies), _1, _2, member_ptr));
1375 #ifndef LUABIND_NO_ERROR_CHECKING
1376 add_setter(
1377 name
1378 , boost::bind<int>(detail::auto_set<T,D,detail::null_type>(), _1, _2, member_ptr)
1379 , &detail::set_matcher<D, detail::null_type>::apply
1380 , &detail::get_setter_signature<D>::apply);
1381 #else
1382 add_setter(name, boost::bind<int>(detail::auto_set<T,D,detail::null_type>(), _1, _2, member_ptr));
1383 #endif
1384 return *this;
1387 template<class D, class GetPolicies, class SetPolicies>
1388 class_& def_readwrite(const char* name, D T::*member_ptr, const GetPolicies& get_policies, const SetPolicies& set_policies)
1390 add_getter(name, boost::bind<int>(detail::auto_get<T,D,GetPolicies>(get_policies), _1, _2, member_ptr));
1391 #ifndef LUABIND_NO_ERROR_CHECKING
1392 add_setter(
1393 name
1394 , boost::bind<int>(detail::auto_set<T,D,SetPolicies>(), _1, _2, member_ptr)
1395 , &detail::set_matcher<D, SetPolicies>::apply
1396 , &detail::get_setter_signature<D>::apply);
1397 #else
1398 add_setter(name, boost::bind<int>(detail::auto_set<T,D,SetPolicies>(set_policies), _1, _2, member_ptr));
1399 #endif
1400 return *this;
1403 template<class op_id, class Left, class Right, class Policies>
1404 class_& def(detail::operator_<op_id, Left, Right>, const Policies& policies)
1406 typedef typename detail::operator_unwrapper<Policies, op_id, T, Left, Right> op_type;
1407 #ifndef LUABIND_NO_ERROR_CHECKING
1408 add_operator(op_type::get_id()
1409 , &op_type::execute
1410 , &op_type::match
1411 , &detail::get_signature<constructor<typename op_type::left_t, typename op_type::right_t> >::apply
1412 , detail::is_unary(op_type::get_id()) ? 1 : 2);
1413 #else
1414 add_operator(op_type::get_id()
1415 , &op_type::execute
1416 , &op_type::match
1417 , detail::is_unary(op_type::get_id()) ? 1 : 2);
1418 #endif
1419 return *this;
1422 template<class op_id, class Left, class Right>
1423 class_& def(detail::operator_<op_id, Left, Right>)
1425 typedef typename detail::operator_unwrapper<detail::null_type, op_id, T, Left, Right> op_type;
1427 #ifndef LUABIND_NO_ERROR_CHECKING
1428 add_operator(op_type::get_id()
1429 , &op_type::execute
1430 , &op_type::match
1431 , &detail::get_signature<constructor<LUABIND_MSVC_TYPENAME op_type::left_t, LUABIND_MSVC_TYPENAME op_type::right_t> >::apply
1432 , detail::is_unary(op_type::get_id()) ? 1 : 2);
1433 #else
1434 add_operator(op_type::get_id()
1435 , &op_type::execute
1436 , &op_type::match
1437 , detail::is_unary(op_type::get_id()) ? 1 : 2);
1438 #endif
1439 return *this;
1442 template<class Signature, bool Constant>
1443 class_& def(detail::application_operator<Signature, Constant>*)
1445 typedef detail::application_operator<Signature, Constant, detail::null_type> op_t;
1447 int arity = detail::calc_arity<Signature::arity>::apply(Signature(), static_cast<detail::null_type*>(0));
1449 #ifndef LUABIND_NO_ERROR_CHECKING
1450 add_operator(detail::op_call, &op_t::template apply<T>::execute, &op_t::match, &detail::get_signature<Signature>::apply, arity + 1);
1451 #else
1452 add_operator(detail::op_call, &op_t::template apply<T>::execute, &op_t::match, arity + 1);
1453 #endif
1455 return *this;
1458 template<class Signature, bool Constant, class Policies>
1459 class_& def(detail::application_operator<Signature, Constant>*, const Policies& policies)
1461 typedef detail::application_operator<Signature, Constant, Policies> op_t;
1463 int arity = detail::calc_arity<Signature::arity>::apply(Signature(), static_cast<Policies*>(0));
1465 #ifndef LUABIND_NO_ERROR_CHECKING
1466 add_operator(detail::op_call, &op_t::template apply<T>::execute, &op_t::match, &detail::get_signature<Signature>::apply, arity + 1);
1467 #else
1468 add_operator(detail::op_call, &op_t::template apply<T>::execute, &op_t::match, arity + 1);
1469 #endif
1471 return *this;
1474 detail::enum_maker<self_t> enum_(const char*)
1476 return detail::enum_maker<self_t>(*this);
1479 class_& operator[](detail::scope s)
1481 this->add_inner_scope(s);
1482 return *this;
1485 private:
1487 void init()
1489 typedef typename detail::extract_parameter<
1490 boost::mpl::list3<X1,X2,X3>
1491 , boost::mpl::or_<
1492 detail::is_bases<boost::mpl::_>
1493 , boost::is_base_and_derived<boost::mpl::_, T>
1495 , no_bases
1496 >::type bases_t;
1498 typedef typename
1499 boost::mpl::if_<detail::is_bases<bases_t>
1500 , bases_t
1501 , bases<bases_t>
1502 >::type Base;
1504 class_base::init(LUABIND_TYPEID(T)
1505 , detail::internal_holder_type<HeldType>::apply()
1506 , detail::pointee_typeid(
1507 get_const_holder(static_cast<HeldType*>(0)))
1508 , detail::internal_holder_extractor<HeldType>::apply(detail::type<T>())
1509 , detail::internal_const_holder_extractor<HeldType>::apply(detail::type<T>())
1510 , detail::const_converter<HeldType>::apply(
1511 luabind::get_const_holder((HeldType*)0))
1512 , detail::holder_constructor<HeldType>::apply(detail::type<T>())
1513 , detail::const_holder_constructor<HeldType>::apply(detail::type<T>())
1514 , detail::internal_holder_destructor<HeldType>::apply(detail::type<T>())
1515 , detail::internal_const_holder_destructor<HeldType>::apply(detail::type<T>())
1516 , detail::internal_holder_size<HeldType>::apply()
1517 , detail::get_holder_alignment<HeldType>::apply());
1519 generate_baseclass_list(detail::type<Base>());
1522 template<class Getter, class GetPolicies>
1523 class_& property_impl(const char* name,
1524 Getter g,
1525 GetPolicies policies,
1526 boost::mpl::bool_<true>)
1528 add_getter(name, boost::bind<int>(detail::get_caller<T,Getter,GetPolicies>(policies), _1, _2, g));
1529 return *this;
1532 template<class Getter, class Setter>
1533 class_& property_impl(const char* name,
1534 Getter g,
1535 Setter s,
1536 boost::mpl::bool_<false>)
1538 add_getter(name, boost::bind<int>(detail::get_caller<T,Getter,detail::null_type>(), _1, _2, g));
1539 #ifndef LUABIND_NO_ERROR_CHECKING
1540 add_setter(
1541 name
1542 , boost::bind<int>(detail::set_caller<T, Setter, detail::null_type>(), _1, _2, s)
1543 , detail::gen_set_matcher((Setter)0, (detail::null_type*)0)
1544 , &detail::get_member_signature<Setter>::apply);
1545 #else
1546 add_setter(name, boost::bind<int>(detail::set_caller<T,Setter,detail::null_type>(), _1, _2, s));
1547 #endif
1548 return *this;
1554 #endif // LUABIND_CLASS_HPP_INCLUDED