moved around some code
[luabind.git] / luabind / class.hpp
blobd0332fb5147049dab5cb18dc378288cd589b3385
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/config.hpp>
81 #include <string>
82 #include <map>
83 #include <vector>
84 #include <cassert>
86 #include <boost/static_assert.hpp>
87 #include <boost/type_traits.hpp>
88 #include <boost/bind.hpp>
89 #include <boost/function.hpp>
90 #include <boost/preprocessor/repetition/enum_params.hpp>
91 #include <boost/preprocessor/repetition/enum_params_with_a_default.hpp>
92 #include <boost/preprocessor/repetition/repeat.hpp>
93 #include <boost/type_traits/is_same.hpp>
94 #include <boost/mpl/list.hpp>
95 #include <boost/mpl/apply.hpp>
96 #include <boost/mpl/lambda.hpp>
97 #include <boost/mpl/logical.hpp>
98 #include <boost/mpl/find_if.hpp>
99 #include <boost/mpl/apply_if.hpp>
100 #include <boost/mpl/logical.hpp>
102 #include <luabind/config.hpp>
103 #include <luabind/scope.hpp>
104 #include <luabind/detail/constructor.hpp>
105 #include <luabind/detail/call.hpp>
106 #include <luabind/detail/signature_match.hpp>
107 #include <luabind/detail/primitives.hpp>
108 #include <luabind/detail/property.hpp>
109 #include <luabind/detail/typetraits.hpp>
110 #include <luabind/detail/class_rep.hpp>
111 #include <luabind/detail/method_rep.hpp>
112 #include <luabind/detail/construct_rep.hpp>
113 #include <luabind/detail/object_rep.hpp>
114 #include <luabind/detail/operators.hpp>
115 #include <luabind/detail/calc_arity.hpp>
116 #include <luabind/detail/call_member.hpp>
117 #include <luabind/detail/enum_maker.hpp>
118 #include <luabind/detail/get_signature.hpp>
119 #include <luabind/detail/implicit_cast.hpp>
120 #include <luabind/detail/operator_id.hpp>
121 #include <luabind/detail/pointee_typeid.hpp>
123 //#include <boost/langbinding/inheritance.hpp>
125 namespace luabind
127 namespace detail
129 struct unspecified {};
132 using detail::type;
134 template<class T, class X1 = detail::unspecified, class X2 = detail::unspecified, class X3 = detail::unspecified>
135 struct class_;
137 // TODO: this function will only be invoked if the user hasn't defined a correct overload
138 // maybe we should have a static assert in here?
139 inline detail::null_type* get_const_holder(...)
141 return 0;
144 namespace detail
146 template<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_BASES, class A)>
147 double is_bases_helper(const bases<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_BASES, A)>&);
149 #ifndef BOOST_MSVC
150 template<class T>
151 char is_bases_helper(const T&);
152 #else
153 char is_bases_helper(...);
154 #endif
156 template<class T>
157 struct is_bases
159 static const T& t;
161 BOOST_STATIC_CONSTANT(bool, value = sizeof(is_bases_helper(t)) == sizeof(double));
162 typedef boost::mpl::bool_<value> type;
163 BOOST_MPL_AUX_LAMBDA_SUPPORT(1,is_bases,(T))
166 double is_not_unspecified_helper(const unspecified*);
167 char is_not_unspecified_helper(...);
169 template<class T>
170 struct is_not_unspecified
172 BOOST_STATIC_CONSTANT(bool, value = sizeof(is_not_unspecified_helper(static_cast<T*>(0))) == sizeof(char));
173 typedef boost::mpl::bool_<value> type;
174 BOOST_MPL_AUX_LAMBDA_SUPPORT(1,is_not_unspecified,(T))
177 template<class Predicate>
178 struct get_predicate
180 typedef typename boost::mpl::and_<
181 Predicate
182 , is_not_unspecified<boost::mpl::_1>
183 > type;
186 template<class Parameters, class Predicate, class DefaultValue>
187 struct extract_parameter
189 typedef typename get_predicate<Predicate>::type pred;
190 typedef typename boost::mpl::find_if<Parameters, pred>::type iterator;
191 typedef typename boost::mpl::apply_if<boost::is_same<iterator, typename boost::mpl::end<Parameters>::type>
192 , boost::mpl::identity<DefaultValue>
193 , iterator
194 >::type type;
197 // this should know about the smart pointer type.
198 // and should really do:
199 // get_pointer(*static_cast<SmartPointer*>(obj_ptr))
200 // to extract the held pointer.
201 template<class HeldType, class T, class F, class Policies>
202 struct function_callback_non_null : Policies
204 function_callback_non_null(F f_): f(f_) {}
205 inline int operator()(lua_State* L, void* obj_ptr)
207 // HeldType& held_obj = *static_cast<HeldType*>(obj_ptr);
208 // T* ptr = static_cast<T*>(luabind::get_pointer(held_obj));
209 // is this correct?
210 T* ptr = static_cast<T*>(obj_ptr);
212 return call(f, ptr, L, static_cast<Policies*>(this));
214 F f;
217 template<class T, class F, class Policies>
218 struct function_callback_null_type : Policies
220 function_callback_null_type(F f_): f(f_) {}
221 inline int operator()(lua_State* L, void* obj_ptr)
223 // std::cout << "HeldType: null_type\n";
224 T* ptr = static_cast<T*>(obj_ptr);
225 return call(f, ptr, L, static_cast<Policies*>(this));
227 F f;
230 template<class HeldType, class T, class F, class Policies>
231 struct function_callback_s
233 typedef typename
234 boost::mpl::if_<boost::is_same<HeldType,detail::null_type>
235 , function_callback_null_type<T,F,Policies>
236 , function_callback_non_null<HeldType,T,F,Policies>
237 >::type type;
240 template<class T, class F, class Policies>
241 struct match_function_callback_s
243 static inline int apply(lua_State* L)
245 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, 1));
246 F fptr = 0;
247 return match(fptr, L, obj->flags() & object_rep::constant, static_cast<Policies*>(0));
251 // prints the types of the values on the stack, in the
252 // range [start_index, lua_gettop()]
254 LUABIND_API std::string stack_content_by_name(lua_State* L, int start_index);
256 struct LUABIND_API create_class
258 static int stage1(lua_State* L);
259 static int stage2(lua_State* L);
262 template<class Type>
263 struct register_wrapped_type
265 template<class Signature, class Policies>
266 static void apply(detail::construct_rep::overload_t& o, const Signature*, const Policies*)
268 o.set_wrapped_constructor(
269 &detail::construct_wrapped_class<Type, Policies, Signature>::apply
274 template<>
275 struct register_wrapped_type<detail::null_type>
277 template<class Signature, class Policies>
278 static void apply(detail::construct_rep::overload_t&, const Signature*, const Policies*) {}
282 // if the class is held by a smart pointer, we need to be able to
283 // implicitly dereference the pointer when needed.
285 template<class UnderlyingT, class HeldT>
286 struct extract_underlying_type
288 static void* extract(void* ptr)
290 HeldT& held_obj = *reinterpret_cast<HeldT*>(ptr);
291 UnderlyingT* underlying_ptr = static_cast<UnderlyingT*>(get_pointer(held_obj));
292 return underlying_ptr;
296 template<class UnderlyingT, class HeldT>
297 struct extract_underlying_const_type
299 static const void* extract(void* ptr)
301 HeldT& held_obj = *reinterpret_cast<HeldT*>(ptr);
302 const UnderlyingT* underlying_ptr = static_cast<const UnderlyingT*>(get_pointer(held_obj));
303 return underlying_ptr;
307 template<class HeldType>
308 struct internal_holder_extractor
310 typedef void*(*extractor_fun)(void*);
312 template<class T>
313 static extractor_fun apply(detail::type<T>)
315 return &detail::extract_underlying_type<T, HeldType>::extract;
319 template<>
320 struct internal_holder_extractor<detail::null_type>
322 typedef void*(*extractor_fun)(void*);
324 template<class T>
325 static extractor_fun apply(detail::type<T>)
327 return 0;
332 template<class HeldType, class ConstHolderType>
333 struct convert_holder
335 static void apply(void* holder, void* target)
337 new(target) ConstHolderType(*reinterpret_cast<HeldType*>(holder));
342 template<class HeldType>
343 struct const_converter
345 typedef void(*converter_fun)(void*, void*);
347 template<class ConstHolderType>
348 static converter_fun apply(ConstHolderType*)
350 return &detail::convert_holder<HeldType, ConstHolderType>::apply;
354 template<>
355 struct const_converter<detail::null_type>
357 typedef void(*converter_fun)(void*, void*);
359 template<class T>
360 static converter_fun apply(T*)
362 return 0;
369 template<class HeldType>
370 struct internal_const_holder_extractor
372 typedef const void*(*extractor_fun)(void*);
374 template<class T>
375 static extractor_fun apply(detail::type<T>)
377 return get_extractor(detail::type<T>(), luabind::get_const_holder(static_cast<HeldType*>(0)));
379 private:
380 template<class T, class ConstHolderType>
381 static extractor_fun get_extractor(detail::type<T>, ConstHolderType*)
383 return &detail::extract_underlying_const_type<T, ConstHolderType>::extract;
387 template<>
388 struct internal_const_holder_extractor<detail::null_type>
390 typedef const void*(*extractor_fun)(void*);
392 template<class T>
393 static extractor_fun apply(detail::type<T>)
395 return 0;
401 // this is simply a selector that returns the type_info
402 // of the held type, or invalid_type_info if we don't have
403 // a held_type
404 template<class HeldType>
405 struct internal_holder_type
407 static LUABIND_TYPE_INFO apply()
409 return LUABIND_TYPEID(HeldType);
413 template<>
414 struct internal_holder_type<detail::null_type>
416 static LUABIND_TYPE_INFO apply()
418 return LUABIND_INVALID_TYPE_INFO;
423 // this is the actual held_type constructor
424 template<class HeldType, class T>
425 struct internal_construct_holder
427 static void apply(void* target, void* raw_pointer)
429 new(target) HeldType(static_cast<T*>(raw_pointer));
433 // the following two functions are the ones that returns
434 // a pointer to a held_type_constructor, or 0 if there
435 // is no held_type
436 template<class HeldType>
437 struct holder_constructor
439 typedef void(*constructor)(void*,void*);
440 template<class T>
441 static constructor apply(detail::type<T>)
443 return &internal_construct_holder<HeldType, T>::apply;
447 template<>
448 struct holder_constructor<detail::null_type>
450 typedef void(*constructor)(void*,void*);
451 template<class T>
452 static constructor apply(detail::type<T>)
454 return 0;
458 // the following two functions are the ones that returns
459 // a pointer to a const_held_type_constructor, or 0 if there
460 // is no held_type
461 template<class HolderType>
462 struct const_holder_constructor
464 typedef void(*constructor)(void*,void*);
465 template<class T>
466 static constructor apply(detail::type<T>)
468 return get_const_holder_constructor(detail::type<T>(), luabind::get_const_holder(static_cast<HolderType*>(0)));
471 private:
473 template<class T, class ConstHolderType>
474 static constructor get_const_holder_constructor(detail::type<T>, ConstHolderType*)
476 return &internal_construct_holder<ConstHolderType, T>::apply;
480 template<>
481 struct const_holder_constructor<detail::null_type>
483 typedef void(*constructor)(void*,void*);
484 template<class T>
485 static constructor apply(detail::type<T>)
487 return 0;
493 // this is a selector that returns the size of the held_type
494 // or 0 if we don't have a held_type
495 template <class HolderType>
496 struct internal_holder_size
498 static int apply() { return get_internal_holder_size(luabind::get_const_holder(static_cast<HolderType*>(0))); }
499 private:
500 template<class ConstHolderType>
501 static int get_internal_holder_size(ConstHolderType*)
503 return max_c<sizeof(HolderType), sizeof(ConstHolderType)>::value;
507 template <>
508 struct internal_holder_size<detail::null_type>
510 static int apply() { return 0; }
514 // if we have a held type, return the destructor to it
515 // note the difference. The held_type should only be destructed (not deleted)
516 // since it's constructed in the lua userdata
517 template<class HeldType>
518 struct internal_holder_destructor
520 typedef void(*destructor_t)(void*);
521 template<class T>
522 static destructor_t apply(detail::type<T>)
524 return &detail::destruct_only_s<HeldType>::apply;
528 // if we don't have a held type, return the destructor of the raw type
529 template<>
530 struct internal_holder_destructor<detail::null_type>
532 typedef void(*destructor_t)(void*);
533 template<class T>
534 static destructor_t apply(detail::type<T>)
536 return &detail::delete_s<T>::apply;
541 // if we have a held type, return the destructor to it's const version
542 template<class HolderType>
543 struct internal_const_holder_destructor
545 typedef void(*destructor_t)(void*);
546 template<class T>
547 static destructor_t apply(detail::type<T>)
549 return const_holder_type_destructor(luabind::get_const_holder(static_cast<HolderType*>(0)));
552 private:
554 template<class ConstHolderType>
555 static destructor_t const_holder_type_destructor(ConstHolderType*)
557 return &detail::destruct_only_s<ConstHolderType>::apply;
562 // if we don't have a held type, return the destructor of the raw type
563 template<>
564 struct internal_const_holder_destructor<detail::null_type>
566 typedef void(*destructor_t)(void*);
567 template<class T>
568 static destructor_t apply(detail::type<T>)
570 return 0;
577 template<class HolderType>
578 struct get_holder_alignment
580 static int apply()
582 return internal_alignment(luabind::get_const_holder(static_cast<HolderType*>(0)));
585 private:
587 template<class ConstHolderType>
588 static int internal_alignment(ConstHolderType*)
590 return detail::max_c<boost::alignment_of<HolderType>::value
591 , boost::alignment_of<ConstHolderType>::value>::value;
595 template<>
596 struct get_holder_alignment<detail::null_type>
598 static int apply()
600 return 1;
605 } // detail
620 struct class_base: detail::scoped_object
622 protected:
624 struct base_desc
626 LUABIND_TYPE_INFO type;
627 int ptr_offset;
630 private:
632 #ifndef NDEBUG
633 bool m_cloned;
634 #endif
636 const char* m_name;
638 std::map<const char*, detail::method_rep, detail::ltstr> m_methods;
640 // datamembers, some members may be readonly, and
641 // only have a getter function
642 std::map<const char*, detail::class_rep::callback, detail::ltstr> m_getters;
643 std::map<const char*, detail::class_rep::callback, detail::ltstr> m_setters;
645 // the operators in lua
646 std::vector<detail::class_rep::operator_callback> m_operators[detail::number_of_operators];
647 std::map<const char*, int, detail::ltstr> m_static_constants;
649 std::vector<base_desc> m_bases;
650 detail::construct_rep m_constructor;
652 void(*m_destructor)(void*);
653 void(*m_const_holder_destructor)(void*);
655 void*(*m_extractor)(void*);
656 const void*(*m_const_extractor)(void*);
658 void(*m_const_converter)(void*,void*);
660 void(*m_construct_holder)(void*, void*);
661 void(*m_construct_const_holder)(void*, void*);
663 int m_holder_size;
664 int m_holder_alignment;
666 LUABIND_TYPE_INFO m_type;
667 LUABIND_TYPE_INFO m_holder_type;
668 LUABIND_TYPE_INFO m_const_holder_type;
670 #ifndef LUABIND_DONT_COPY_STRINGS
671 // the maps that contains char pointers points into
672 // this vector of strings.
673 std::vector<char*> m_strings;
674 #endif
677 public:
679 // public 'cause of enum_maker, FIX
680 void add_static_constant(const char* name, int val)
682 m_static_constants[name] = val;
685 protected:
687 mutable std::vector<detail::scoped_object*> m_children;
689 void init(LUABIND_TYPE_INFO type
690 , LUABIND_TYPE_INFO holder_type
691 , void*(*extractor)(void*)
692 , const void*(*const_extractor)(void*)
693 , void(*const_converter)(void*,void*)
694 , void(*holder_constructor)(void*,void*)
695 , void(*const_holder_constructor)(void*,void*)
696 , void(*destructor)(void*)
697 , void(*const_holder_destructor)(void*)
698 , int holder_size
699 , int holder_alignment)
701 m_type = type;
702 m_holder_type = holder_type;
703 m_extractor = extractor;
704 m_const_extractor = const_extractor;
705 m_const_converter = const_converter;
706 m_construct_holder = holder_constructor;
707 m_construct_const_holder = const_holder_constructor;
708 m_destructor = destructor;
709 m_const_holder_destructor = const_holder_destructor;
710 m_holder_size = holder_size;
711 m_holder_alignment = holder_alignment;
714 template<class T>
715 void set_const_holder_type(T*)
717 m_const_holder_type = LUABIND_TYPEID(T);
720 inline void add_getter(const char* name, const boost::function2<int, lua_State*, int>& g)
722 detail::class_rep::callback c;
723 c.func = g;
724 c.pointer_offset = 0;
725 #ifndef LUABIND_DONT_COPY_STRINGS
726 m_strings.push_back(detail::dup_string(name));
727 m_getters[m_strings.back()] = c;
728 #else
729 m_getters[name] = c;
730 #endif
733 inline void add_setter(const char* name, const boost::function2<int, lua_State*, int>& s)
735 detail::class_rep::callback c;
736 c.func = s;
737 c.pointer_offset = 0;
738 #ifndef LUABIND_DONT_COPY_STRINGS
739 m_strings.push_back(detail::dup_string(name));
740 m_setters[m_strings.back()] = c;
741 #else
742 m_setters[name] = c;
743 #endif
746 void add_base(const base_desc& b)
748 m_bases.push_back(b);
751 public:
753 void add_constructor(const detail::construct_rep::overload_t& o)
755 m_constructor.overloads.push_back(o);
758 void add_method(const char* name, const detail::overload_rep& o)
760 #ifdef LUABIND_DONT_COPY_STRINGS
761 detail::method_rep& method = m_methods[name];
762 method.name = name;
763 #else
764 m_strings.push_back(detail::dup_string(name));
765 detail::method_rep& method = m_methods[m_strings.back()];
766 method.name = m_strings.back();
767 #endif
768 method.add_overload(o);
769 method.crep = 0;
772 #ifndef LUABIND_NO_ERROR_CHECKING
773 inline void add_operator(int op_id, int(*func)(lua_State*), int(*matcher)(lua_State*), void(*sig)(lua_State*, std::string&), int arity)
774 #else
775 inline void add_operator(int op_id, int(*func)(lua_State*), int(*matcher)(lua_State*), int arity)
776 #endif
778 detail::class_rep::operator_callback o;
779 o.set_fun(func);
780 o.set_match_fun(matcher);
781 o.set_arity(arity);
783 #ifndef LUABIND_NO_ERROR_CHECKING
785 o.set_sig_fun(sig);
787 #endif
788 m_operators[op_id].push_back(o);
797 const char* name() const { return m_name; }
799 class_base(const char* name)
801 #ifndef LUABIND_DONT_COPY_STRINGS
802 m_strings.push_back(detail::dup_string(name));
803 m_name = m_strings.back();
804 #else
805 m_name = name;
806 #endif
808 #ifndef NDEBUG
809 m_cloned = false;
810 #endif
813 virtual ~class_base()
815 for (std::vector<detail::scoped_object*>::iterator
816 i = m_children.begin(); i != m_children.end(); ++i)
817 delete *i;
819 // if we are copying strings, we have to destroy them too
820 #ifndef LUABIND_DONT_COPY_STRINGS
821 for (std::vector<char*>::iterator i = m_strings.begin(); i != m_strings.end(); ++i)
822 delete[] *i;
823 #endif
826 // pushes the class_rep on the lua stack
827 virtual void commit(lua_State* L)
829 assert(!m_cloned && "class already commited");
831 detail::getref(L, scope_stack::top(L));
832 lua_pushstring(L, m_name);
834 detail::class_rep* crep;
836 detail::class_registry* r = detail::class_registry::get_registry(L);
837 // create a class_rep structure for this class.
838 // allocate it within lua to let lua collect it on
839 // lua_close(). This is better than allocating it
840 // as a static, since it will then be destructed
841 // when the program exits instead.
842 // warning: we assume that lua will not
843 // move the userdata memory.
844 lua_newuserdata(L, sizeof(detail::class_rep));
845 crep = reinterpret_cast<detail::class_rep*>(lua_touserdata(L, -1));
847 new(crep) detail::class_rep( m_type
848 , m_name
850 , m_destructor
851 , m_const_holder_destructor
852 , m_holder_type
853 , m_const_holder_type
854 , m_extractor
855 , m_const_extractor
856 , m_const_converter
857 , m_construct_holder
858 , m_construct_const_holder
859 , m_holder_size
860 , m_holder_alignment);
862 // register this new type in the class registry
863 r->add_class(m_type, crep);
864 if (!(LUABIND_TYPE_INFO_EQUAL(m_holder_type, LUABIND_INVALID_TYPE_INFO)))
866 // if we have a held type
867 // we have to register it in the class-table
868 // but only for the base class, if it already
869 // exists, we don't have to register it
870 detail::class_rep* c = r->find_class(m_holder_type);
871 if (c == 0)
873 r->add_class(m_holder_type, crep);
874 r->add_class(m_const_holder_type, crep);
878 // constructors
879 m_constructor.swap(crep->m_constructor);
881 #ifndef LUABIND_DONT_COPY_STRINGS
882 assert(crep->m_strings.empty() && "Internal error");
883 std::swap(crep->m_strings, m_strings);
884 #endif
886 std::swap(crep->m_getters, m_getters);
887 std::swap(crep->m_setters, m_setters);
889 for(int i = 0; i < detail::number_of_operators; ++i)
890 std::swap(crep->m_operators[i], m_operators[i]);
892 std::swap(crep->m_static_constants, m_static_constants);
894 // here!
895 // crep->m_methods = m_methods;
897 for (std::vector<base_desc>::iterator i = m_bases.begin();
898 i != m_bases.end();
899 ++i)
901 detail::class_registry* r = detail::class_registry::get_registry(L);
903 // the baseclass' class_rep structure
904 detail::class_rep* bcrep = r->find_class(i->type);
906 detail::class_rep::base_info base;
907 base.pointer_offset = i->ptr_offset;
908 base.base = bcrep;
910 crep->add_base_class(base);
912 typedef std::map<const char*, detail::method_rep, detail::ltstr> methods_t;
914 for (methods_t::const_iterator i
915 = bcrep->m_methods.begin()
916 ; i != bcrep->m_methods.end()
917 ; ++i)
919 detail::method_rep& m = m_methods[i->first];
921 typedef std::vector<detail::overload_rep> overloads_t;
923 for (overloads_t::const_iterator j
924 = i->second.overloads().begin()
925 ; j != i->second.overloads().end()
926 ; ++j)
928 detail::overload_rep o = *j;
929 o.add_offset(base.pointer_offset);
930 m.add_overload(o);
934 // copy base class table
935 detail::getref(L, crep->table_ref());
936 detail::getref(L, bcrep->table_ref());
937 lua_pushnil(L);
939 while (lua_next(L, -2))
941 lua_pushvalue(L, -2); // copy key
942 lua_insert(L, -2);
943 lua_settable(L, -5);
946 lua_pop(L, 2);
949 crep->m_methods = m_methods;
951 for (std::map<const char*, detail::method_rep, detail::ltstr>::iterator i
952 = crep->m_methods.begin(); i != crep->m_methods.end(); ++i)
954 i->second.crep = crep;
957 // add methods
958 for (std::map<const char*, detail::method_rep, detail::ltstr>::iterator i
959 = m_methods.begin(); i != m_methods.end(); ++i)
961 detail::getref(L, crep->table_ref());
962 lua_pushstring(L, i->first);
963 lua_pushnil(L);
964 lua_settable(L, -3);
965 lua_pop(L, 1);
967 crep->add_method(L, i->first, crep->m_methods[i->first]);
968 i->second.crep = crep;
971 m_methods.clear();
973 lua_settable(L, -3);
974 lua_pop(L, 1);
978 // destructive copy
979 virtual luabind::detail::scoped_object* clone()
981 assert(m_cloned == false);
983 #ifndef NDEBUG
984 m_cloned = true;
985 #endif
987 class_base* ret = new class_base(m_name);
989 std::swap(ret->m_getters, m_getters);
990 std::swap(ret->m_setters, m_setters);
992 for(int i = 0; i < detail::number_of_operators; ++i)
993 std::swap(ret->m_operators[i], m_operators[i]);
995 std::swap(ret->m_static_constants, m_static_constants);
997 ret->init(m_type
998 , m_holder_type
999 , m_extractor
1000 , m_const_extractor
1001 , m_const_converter
1002 , m_construct_holder
1003 , m_construct_const_holder
1004 , m_destructor
1005 , m_const_holder_destructor
1006 , m_holder_size
1007 , m_holder_alignment);
1009 ret->m_const_holder_type = m_const_holder_type;
1011 ret->m_bases.swap(m_bases);
1012 ret->m_methods.swap(m_methods);
1013 m_constructor.swap(ret->m_constructor);
1015 ret->m_name = m_name;
1017 #ifndef LUABIND_DONT_COPY_STRINGS
1018 std::swap(ret->m_strings, m_strings);
1019 #endif
1021 m_children.swap(ret->m_children);
1023 return ret;
1027 namespace detail {
1029 struct class_registration;
1031 struct class_base : detail::scope
1033 public:
1034 class_base(char const* name);
1036 struct base_desc
1038 LUABIND_TYPE_INFO type;
1039 int ptr_offset;
1042 void init(
1043 LUABIND_TYPE_INFO type
1044 , LUABIND_TYPE_INFO holder_type
1045 , LUABIND_TYPE_INFO const_holder_type
1046 , void*(*extractor)(void*)
1047 , const void*(*const_extractor)(void*)
1048 , void(*const_converter)(void*,void*)
1049 , void(*holder_constructor)(void*,void*)
1050 , void(*const_holder_constructor)(void*,void*)
1051 , void(*destructor)(void*)
1052 , void(*const_holder_destructor)(void*)
1053 , int holder_size
1054 , int holder_alignment);
1056 void add_getter(
1057 const char* name
1058 , const boost::function2<int, lua_State*, int>& g);
1060 #ifdef LUABIND_NO_ERROR_CHECKING
1061 void class_base::add_setter(
1062 const char* name
1063 , const boost::function2<int, lua_State*, int>& s);
1064 #else
1065 void class_base::add_setter(
1066 const char* name
1067 , const boost::function2<int, lua_State*, int>& s
1068 , int (*match)(lua_State*, int)
1069 , void (*get_sig_ptr)(lua_State*, std::string&));
1070 #endif
1072 void add_base(const base_desc& b);
1073 void add_constructor(const detail::construct_rep::overload_t& o);
1074 void add_method(const char* name, const detail::overload_rep& o);
1076 #ifndef LUABIND_NO_ERROR_CHECKING
1077 void add_operator(
1078 int op_id
1079 , int(*func)(lua_State*)
1080 , int(*matcher)(lua_State*)
1081 , void(*sig)(lua_State*
1082 , std::string&)
1083 , int arity);
1084 #else
1085 void add_operator(
1086 int op_id
1087 , int(*func)(lua_State*)
1088 , int(*matcher)(lua_State*)
1089 , int arity);
1090 #endif
1092 const char* name() const;
1094 void add_static_constant(const char* name, int val);
1095 void add_inner_scope(scope& s);
1097 private:
1098 class_registration* m_registration;
1101 } // namespace detail
1103 // registers a class in the lua environment
1104 template<class T, class X1, class X2, class X3>
1105 struct class_: detail::class_base
1107 typedef class_<T, X1, X2, X3> self_t;
1109 private:
1111 template<class A, class B, class C, class D>
1112 class_(const class_<A,B,C,D>&);
1114 public:
1116 // WrappedType MUST inherit from T
1117 typedef typename detail::extract_parameter<
1118 boost::mpl::vector3<X1,X2,X3>
1119 , boost::is_base_and_derived<T, boost::mpl::_>
1120 /* , boost::mpl::not_<
1121 boost::mpl::or_<
1122 detail::is_bases<boost::mpl::_>
1123 , boost::is_base_and_derived<boost::mpl::_, T>
1126 , detail::null_type
1127 >::type WrappedType;
1129 typedef typename detail::extract_parameter<
1130 boost::mpl::list3<X1,X2,X3>
1131 , boost::mpl::not_<
1132 boost::mpl::or_<
1133 boost::mpl::or_<
1134 detail::is_bases<boost::mpl::_>
1135 , boost::is_base_and_derived<boost::mpl::_, T>
1137 , boost::is_base_and_derived<T, boost::mpl::_>
1140 , detail::null_type
1141 >::type HeldType;
1143 template<class To>
1144 void register_downcast(boost::mpl::true_, detail::type<To>* = 0)
1145 { boost::langbinding::register_conversion<To, T>(true); }
1147 template<class To>
1148 void register_downcast(boost::mpl::false_, detail::type<To>* = 0)
1151 // this function generates conversion information
1152 // in the given class_rep structure. It will be able
1153 // to implicitly cast to the given template type
1154 template<class To>
1155 void gen_base_info(detail::type<To>)
1157 // boost::langbinding::register_dynamic_id<To>();
1158 // boost::langbinding::register_conversion<T, To>(false);
1160 // register_downcast<To>(boost::mpl::bool_<boost::is_polymorphic<To>::value>());
1162 // fist, make sure the given base class is registered.
1163 // if it's not registered we can't push it's lua table onto
1164 // the stack because it doesn't have a table
1166 // try to cast this type to the base type and remember
1167 // the pointer offset. For multiple inheritance the pointer
1168 // may change when casting. Since we need to be able to
1169 // cast we need this pointer offset.
1170 // store the information in this class' base class-vector
1171 base_desc base;
1172 base.type = LUABIND_TYPEID(To);
1173 base.ptr_offset = detail::ptr_offset(detail::type<T>(), detail::type<To>());
1174 add_base(base);
1177 void gen_base_info(detail::type<detail::null_type>)
1180 #define LUABIND_GEN_BASE_INFO(z, n, text) gen_base_info(detail::type<B##n>());
1182 template<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_BASES, class B)>
1183 void generate_baseclass_list(detail::type<bases<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_BASES, B)> >)
1185 BOOST_PP_REPEAT(LUABIND_MAX_BASES, LUABIND_GEN_BASE_INFO, _)
1188 #undef LUABIND_GEN_BASE_INFO
1190 // this is the internal version of def() it is run from both overloads
1191 // of def. It has two versions, one where a contstructor is registered
1192 // and one where a function is registered
1193 template<class Policies>
1194 struct internal_def_s
1196 template<class F>
1197 static void apply(const char* name, F f, detail::class_base* c)
1199 // std::cout << "HeldType2: " << typeid(HeldType).name() << "\n";
1201 detail::overload_rep o(f, static_cast<Policies*>(0));
1203 typedef LUABIND_MSVC_TYPENAME detail::function_callback_s<HeldType,T,F,Policies>::type call_t;
1205 o.set_match_fun(&detail::match_function_callback_s<T,F,Policies>::apply);
1206 o.call_fun = boost::bind<int>(call_t(f), _1, _2);
1208 #ifndef LUABIND_NO_ERROR_CHECKING
1210 o.set_sig_fun(&detail::get_member_signature<F>::apply);
1212 #endif
1214 c->add_method(name, o);
1217 template<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, class A)>
1218 static void apply(constructor<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, A)>, detail::class_base* c)
1220 // std::cout << "HeldType2: " << typeid(HeldType).name() << "\n";
1222 detail::construct_rep::overload_t o;
1224 o.set_constructor(
1225 &detail::construct_class<
1227 ,Policies
1228 ,constructor<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, A)>
1229 >::apply
1232 // if we have a WrappedType, we have to register it's constructor
1233 // but if it's null_type (no WrappedType) we should not register it
1234 detail::register_wrapped_type<WrappedType>::apply(o,
1235 static_cast<const constructor<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, A)>*>(0),
1236 static_cast<const Policies*>(0));
1239 o.set_match_fun(
1240 &detail::constructor_match<
1241 constructor<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, A)>
1243 ,Policies
1244 >::apply);
1246 #ifndef LUABIND_NO_ERROR_CHECKING
1248 o.set_sig_fun(&detail::get_signature<constructor<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, A)> >::apply);
1250 #endif
1252 typedef constructor<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, A)> con_t;
1254 o.set_arity(detail::calc_arity<con_t::arity>::apply(con_t(), static_cast<Policies*>(0)));
1256 c->add_constructor(o);
1260 class_(const char* name): class_base(name) { init(); }
1262 template<class F>
1263 class_& def(const char* name, F f)
1265 internal_def_s<detail::null_type>::apply(name, f, this);
1266 return *this;
1269 template<class F, class Policies>
1270 class_& def(const char* name, F f, const Policies&)
1272 internal_def_s<Policies>::apply(name, f, this);
1273 return *this;
1276 template<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, class A)>
1277 class_& def(constructor<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, A)> sig)
1279 internal_def_s<detail::null_type>::apply(sig, this);
1280 return *this;
1283 template<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, class A), class Policies>
1284 class_& def(constructor<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, A)> sig, const Policies& policies)
1286 internal_def_s<Policies>::apply(sig, this);
1287 return *this;
1290 template<class Getter>
1291 class_& property(const char* name, Getter g)
1293 add_getter(name, boost::bind<int>(detail::get_caller<T, Getter, detail::null_type>(), _1, _2, g));
1294 return *this;
1297 template<class Getter, class MaybeSetter>
1298 class_& property(const char* name, Getter g, MaybeSetter s)
1300 return property_impl(name, g, s, boost::mpl::bool_<detail::is_policy_cons<MaybeSetter>::value>());
1303 template<class Getter, class Setter, class GetPolicies>
1304 class_& property(const char* name, Getter g, Setter s, const GetPolicies& get_policies)
1306 add_getter(name, boost::bind<int>(detail::get_caller<T, Getter, GetPolicies>(get_policies), _1, _2, g));
1307 #ifndef LUABIND_NO_ERROR_CHECKING
1308 add_setter(
1309 name
1310 , boost::bind<int>(detail::set_caller<T, Setter, detail::null_type>(), _1, _2, s)
1311 , detail::gen_set_matcher((Setter)0, (detail::null_type*)0)
1312 , &detail::get_member_signature<Setter>::apply);
1313 #else
1314 add_setter(
1315 name
1316 , boost::bind<int>(detail::set_caller<T, Setter, detail::null_type>(), _1, _2, s));
1317 #endif
1318 return *this;
1321 template<class Getter, class Setter, class GetPolicies, class SetPolicies>
1322 class_& property(const char* name
1323 , Getter g, Setter s
1324 , const GetPolicies& get_policies
1325 , const SetPolicies& set_policies)
1327 add_getter(name, boost::bind<int>(detail::get_caller<T, Getter, GetPolicies>(get_policies), _1, _2, g));
1328 #ifndef LUABIND_NO_ERROR_CHECKING
1329 add_setter(
1330 name
1331 , boost::bind<int>(detail::set_caller<T, Setter, SetPolicies>(), _1, _2, s)
1332 , detail::gen_set_matcher((Setter)0, (SetPolicies*)0)
1333 , &detail::get_member_signature<Setter>::apply);
1334 #else
1335 add_setter(name, boost::bind<int>(detail::set_caller<T, Setter, SetPolicies>(set_policies), _1, _2, s));
1336 #endif
1337 return *this;
1340 template<class D>
1341 class_& def_readonly(const char* name, D T::*member_ptr)
1343 add_getter(name, boost::bind<int>(detail::auto_get<T,D,detail::null_type>(), _1, _2, member_ptr));
1344 return *this;
1347 template<class D, class Policies>
1348 class_& def_readonly(const char* name, D T::*member_ptr, const Policies& policies)
1350 add_getter(name, boost::bind<int>(detail::auto_get<T,D,Policies>(policies), _1, _2, member_ptr));
1351 return *this;
1354 template<class D>
1355 class_& def_readwrite(const char* name, D T::*member_ptr)
1357 add_getter(name, boost::bind<int>(detail::auto_get<T,D,detail::null_type>(), _1, _2, member_ptr));
1358 #ifndef LUABIND_NO_ERROR_CHECKING
1359 add_setter(
1360 name
1361 , boost::bind<int>(detail::auto_set<T,D,detail::null_type>(), _1, _2, member_ptr)
1362 , &detail::set_matcher<D, detail::null_type>::apply
1363 , &detail::get_setter_signature<D>::apply);
1364 #else
1365 add_setter(name, boost::bind<int>(detail::auto_set<T,D,detail::null_type>(), _1, _2, member_ptr));
1366 #endif
1367 return *this;
1370 template<class D, class GetPolicies>
1371 class_& def_readwrite(const char* name, D T::*member_ptr, const GetPolicies& get_policies)
1373 add_getter(name, boost::bind<int>(detail::auto_get<T,D,GetPolicies>(get_policies), _1, _2, member_ptr));
1374 #ifndef LUABIND_NO_ERROR_CHECKING
1375 add_setter(
1376 name
1377 , boost::bind<int>(detail::auto_set<T,D,detail::null_type>(), _1, _2, member_ptr)
1378 , &detail::set_matcher<D, detail::null_type>::apply
1379 , &detail::get_setter_signature<D>::apply);
1380 #else
1381 add_setter(name, boost::bind<int>(detail::auto_set<T,D,detail::null_type>(), _1, _2, member_ptr));
1382 #endif
1383 return *this;
1386 template<class D, class GetPolicies, class SetPolicies>
1387 class_& def_readwrite(const char* name, D T::*member_ptr, const GetPolicies& get_policies, const SetPolicies& set_policies)
1389 add_getter(name, boost::bind<int>(detail::auto_get<T,D,GetPolicies>(get_policies), _1, _2, member_ptr));
1390 #ifndef LUABIND_NO_ERROR_CHECKING
1391 add_setter(
1392 name
1393 , boost::bind<int>(detail::auto_set<T,D,SetPolicies>(), _1, _2, member_ptr)
1394 , &detail::set_matcher<D, SetPolicies>::apply
1395 , &detail::get_setter_signature<D>::apply);
1396 #else
1397 add_setter(name, boost::bind<int>(detail::auto_set<T,D,SetPolicies>(set_policies), _1, _2, member_ptr));
1398 #endif
1399 return *this;
1402 template<class op_id, class Left, class Right, class Policies>
1403 class_& def(detail::operator_<op_id, Left, Right>, const Policies& policies)
1405 typedef typename detail::operator_unwrapper<Policies, op_id, T, Left, Right> op_type;
1406 #ifndef LUABIND_NO_ERROR_CHECKING
1407 add_operator(op_type::get_id()
1408 , &op_type::execute
1409 , &op_type::match
1410 , &detail::get_signature<constructor<typename op_type::left_t, typename op_type::right_t> >::apply
1411 , detail::is_unary(op_type::get_id()) ? 1 : 2);
1412 #else
1413 add_operator(op_type::get_id()
1414 , &op_type::execute
1415 , &op_type::match
1416 , detail::is_unary(op_type::get_id()) ? 1 : 2);
1417 #endif
1418 return *this;
1421 template<class op_id, class Left, class Right>
1422 class_& def(detail::operator_<op_id, Left, Right>)
1424 typedef typename detail::operator_unwrapper<detail::null_type, op_id, T, Left, Right> op_type;
1426 #ifndef LUABIND_NO_ERROR_CHECKING
1427 add_operator(op_type::get_id()
1428 , &op_type::execute
1429 , &op_type::match
1430 , &detail::get_signature<constructor<LUABIND_MSVC_TYPENAME op_type::left_t, LUABIND_MSVC_TYPENAME op_type::right_t> >::apply
1431 , detail::is_unary(op_type::get_id()) ? 1 : 2);
1432 #else
1433 add_operator(op_type::get_id()
1434 , &op_type::execute
1435 , &op_type::match
1436 , detail::is_unary(op_type::get_id()) ? 1 : 2);
1437 #endif
1438 return *this;
1441 template<class Signature, bool Constant>
1442 class_& def(detail::application_operator<Signature, Constant>*)
1444 typedef detail::application_operator<Signature, Constant, detail::null_type> op_t;
1446 int arity = detail::calc_arity<Signature::arity>::apply(Signature(), static_cast<detail::null_type*>(0));
1448 #ifndef LUABIND_NO_ERROR_CHECKING
1449 add_operator(detail::op_call, &op_t::template apply<T>::execute, &op_t::match, &detail::get_signature<Signature>::apply, arity + 1);
1450 #else
1451 add_operator(detail::op_call, &op_t::template apply<T>::execute, &op_t::match, arity + 1);
1452 #endif
1454 return *this;
1457 template<class Signature, bool Constant, class Policies>
1458 class_& def(detail::application_operator<Signature, Constant>*, const Policies& policies)
1460 typedef detail::application_operator<Signature, Constant, Policies> op_t;
1462 int arity = detail::calc_arity<Signature::arity>::apply(Signature(), static_cast<Policies*>(0));
1464 #ifndef LUABIND_NO_ERROR_CHECKING
1465 add_operator(detail::op_call, &op_t::template apply<T>::execute, &op_t::match, &detail::get_signature<Signature>::apply, arity + 1);
1466 #else
1467 add_operator(detail::op_call, &op_t::template apply<T>::execute, &op_t::match, arity + 1);
1468 #endif
1470 return *this;
1473 detail::enum_maker<self_t> enum_(const char*)
1475 return detail::enum_maker<self_t>(*this);
1478 class_& operator[](detail::scope s)
1480 this->add_inner_scope(s);
1481 return *this;
1484 private:
1486 void init()
1488 typedef typename detail::extract_parameter<
1489 boost::mpl::list3<X1,X2,X3>
1490 , boost::mpl::or_<
1491 detail::is_bases<boost::mpl::_>
1492 , boost::is_base_and_derived<boost::mpl::_, T>
1494 , no_bases
1495 >::type bases_t;
1497 typedef typename
1498 boost::mpl::if_<detail::is_bases<bases_t>
1499 , bases_t
1500 , bases<bases_t>
1501 >::type Base;
1503 class_base::init(LUABIND_TYPEID(T)
1504 , detail::internal_holder_type<HeldType>::apply()
1505 , detail::pointee_typeid(
1506 get_const_holder(static_cast<HeldType*>(0)))
1507 , detail::internal_holder_extractor<HeldType>::apply(detail::type<T>())
1508 , detail::internal_const_holder_extractor<HeldType>::apply(detail::type<T>())
1509 , detail::const_converter<HeldType>::apply(
1510 luabind::get_const_holder((HeldType*)0))
1511 , detail::holder_constructor<HeldType>::apply(detail::type<T>())
1512 , detail::const_holder_constructor<HeldType>::apply(detail::type<T>())
1513 , detail::internal_holder_destructor<HeldType>::apply(detail::type<T>())
1514 , detail::internal_const_holder_destructor<HeldType>::apply(detail::type<T>())
1515 , detail::internal_holder_size<HeldType>::apply()
1516 , detail::get_holder_alignment<HeldType>::apply());
1518 generate_baseclass_list(detail::type<Base>());
1521 template<class Getter, class GetPolicies>
1522 class_& property_impl(const char* name,
1523 Getter g,
1524 GetPolicies policies,
1525 boost::mpl::bool_<true>)
1527 add_getter(name, boost::bind<int>(detail::get_caller<T,Getter,GetPolicies>(policies), _1, _2, g));
1528 return *this;
1531 template<class Getter, class Setter>
1532 class_& property_impl(const char* name,
1533 Getter g,
1534 Setter s,
1535 boost::mpl::bool_<false>)
1537 add_getter(name, boost::bind<int>(detail::get_caller<T,Getter,detail::null_type>(), _1, _2, g));
1538 #ifndef LUABIND_NO_ERROR_CHECKING
1539 add_setter(
1540 name
1541 , boost::bind<int>(detail::set_caller<T, Setter, detail::null_type>(), _1, _2, s)
1542 , detail::gen_set_matcher((Setter)0, (detail::null_type*)0)
1543 , &detail::get_member_signature<Setter>::apply);
1544 #else
1545 add_setter(name, boost::bind<int>(detail::set_caller<T,Setter,detail::null_type>(), _1, _2, s));
1546 #endif
1547 return *this;
1553 #endif // LUABIND_CLASS_HPP_INCLUDED