*** empty log message ***
[luabind.git] / luabind / class.hpp
blob8c3eb3f648bddb56c1162ea6d5d5f23c93fd5309
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 cache finalizers in the class_rep. For lua classes
70 we currently do a lookup each time we need to know if a lua class
71 has a finalizer.
73 static functions, this could be implemented by letting classes contain
74 other declarations (classes or functions)
76 document custom policies, custom converters
78 store the instance object for policies.
80 support the __concat metamethod. This is a bit tricky, since it cannot be
81 treated as a normal operator. It is a binary operator but we want to use the
82 __tostring implementation for both arguments.
86 #include <luabind/config.hpp>
88 #include <string>
89 #include <map>
90 #include <vector>
91 #include <cassert>
93 #include <boost/static_assert.hpp>
94 #include <boost/type_traits.hpp>
95 #include <boost/bind.hpp>
96 #include <boost/function.hpp>
97 #include <boost/preprocessor/repetition/enum_params.hpp>
98 #include <boost/preprocessor/repetition/enum_params_with_a_default.hpp>
99 #include <boost/preprocessor/repetition/repeat.hpp>
100 #include <boost/type_traits/is_same.hpp>
101 #include <boost/mpl/list.hpp>
102 #include <boost/mpl/apply.hpp>
103 #include <boost/mpl/lambda.hpp>
104 #include <boost/mpl/logical.hpp>
105 #include <boost/mpl/find_if.hpp>
106 #include <boost/mpl/apply_if.hpp>
107 #include <boost/mpl/logical.hpp>
109 #include <luabind/config.hpp>
110 #include <luabind/scope.hpp>
111 #include <luabind/detail/constructor.hpp>
112 #include <luabind/detail/call.hpp>
113 #include <luabind/detail/signature_match.hpp>
114 #include <luabind/detail/primitives.hpp>
115 #include <luabind/detail/property.hpp>
116 #include <luabind/detail/typetraits.hpp>
117 #include <luabind/detail/class_rep.hpp>
118 #include <luabind/detail/method_rep.hpp>
119 #include <luabind/detail/construct_rep.hpp>
120 #include <luabind/detail/object_rep.hpp>
121 #include <luabind/detail/operators.hpp>
122 #include <luabind/detail/calc_arity.hpp>
123 #include <luabind/detail/call_member.hpp>
124 #include <luabind/detail/enum_maker.hpp>
125 #include <luabind/detail/get_signature.hpp>
126 #include <luabind/detail/implicit_cast.hpp>
127 #include <luabind/detail/operator_id.hpp>
128 #include <luabind/detail/pointee_typeid.hpp>
130 //#include <boost/langbinding/inheritance.hpp>
132 namespace luabind
134 namespace detail
136 struct unspecified {};
139 using detail::type;
141 template<class T, class X1 = detail::unspecified, class X2 = detail::unspecified, class X3 = detail::unspecified>
142 struct class_;
144 // TODO: this function will only be invoked if the user hasn't defined a correct overload
145 // maybe we should have a static assert in here?
146 inline detail::null_type* get_const_holder(...)
148 return 0;
151 namespace detail
153 template<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_BASES, class A)>
154 double is_bases_helper(const bases<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_BASES, A)>&);
156 #ifndef BOOST_MSVC
157 template<class T>
158 char is_bases_helper(const T&);
159 #else
160 char is_bases_helper(...);
161 #endif
163 template<class T>
164 struct is_bases
166 static const T& t;
168 BOOST_STATIC_CONSTANT(bool, value = sizeof(is_bases_helper(t)) == sizeof(double));
169 typedef boost::mpl::bool_<value> type;
170 BOOST_MPL_AUX_LAMBDA_SUPPORT(1,is_bases,(T))
173 double is_not_unspecified_helper(const unspecified*);
174 char is_not_unspecified_helper(...);
176 template<class T>
177 struct is_not_unspecified
179 BOOST_STATIC_CONSTANT(bool, value = sizeof(is_not_unspecified_helper(static_cast<T*>(0))) == sizeof(char));
180 typedef boost::mpl::bool_<value> type;
181 BOOST_MPL_AUX_LAMBDA_SUPPORT(1,is_not_unspecified,(T))
184 template<class Predicate>
185 struct get_predicate
187 typedef typename boost::mpl::and_<
188 Predicate
189 , is_not_unspecified<boost::mpl::_1>
190 > type;
193 template<class Parameters, class Predicate, class DefaultValue>
194 struct extract_parameter
196 typedef typename get_predicate<Predicate>::type pred;
197 typedef typename boost::mpl::find_if<Parameters, pred>::type iterator;
198 typedef typename boost::mpl::apply_if<boost::is_same<iterator, typename boost::mpl::end<Parameters>::type>
199 , boost::mpl::identity<DefaultValue>
200 , iterator
201 >::type type;
204 // TODO: is this detail::class_rep::function_dispatcher or detail::free_functions::function_dispatcher?
205 // LUABIND_API int function_dispatcher(lua_State* L);
207 // this should know about the smart pointer type.
208 // and should really do:
209 // get_pointer(*static_cast<SmartPointer*>(obj_ptr))
210 // to extract the held pointer.
211 template<class HeldType, class T, class F, class Policies>
212 struct function_callback_non_null : Policies
214 function_callback_non_null(F f_): f(f_) {}
215 inline int operator()(lua_State* L, void* obj_ptr)
217 // HeldType& held_obj = *static_cast<HeldType*>(obj_ptr);
218 // T* ptr = static_cast<T*>(luabind::get_pointer(held_obj));
219 // is this correct?
220 T* ptr = static_cast<T*>(obj_ptr);
222 return call(f, ptr, L, static_cast<Policies*>(this));
224 F f;
227 template<class T, class F, class Policies>
228 struct function_callback_null_type : Policies
230 function_callback_null_type(F f_): f(f_) {}
231 inline int operator()(lua_State* L, void* obj_ptr)
233 // std::cout << "HeldType: null_type\n";
234 T* ptr = static_cast<T*>(obj_ptr);
235 return call(f, ptr, L, static_cast<Policies*>(this));
237 F f;
240 template<class HeldType, class T, class F, class Policies>
241 struct function_callback_s
243 typedef typename
244 boost::mpl::if_<boost::is_same<HeldType,detail::null_type>
245 , function_callback_null_type<T,F,Policies>
246 , function_callback_non_null<HeldType,T,F,Policies>
247 >::type type;
250 template<class T, class F, class Policies>
251 struct match_function_callback_s
253 static inline int apply(lua_State* L)
255 object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, 1));
256 F fptr = 0;
257 return match(fptr, L, obj->flags() & object_rep::constant, static_cast<Policies*>(0));
261 // prints the types of the values on the stack, in the
262 // range [start_index, lua_gettop()]
264 LUABIND_API std::string stack_content_by_name(lua_State* L, int start_index);
266 struct LUABIND_API create_class
268 static int stage1(lua_State* L);
269 static int stage2(lua_State* L);
272 template<class Type>
273 struct register_wrapped_type
275 template<class Signature, class Policies>
276 static void apply(detail::construct_rep::overload_t& o, const Signature*, const Policies*)
278 o.set_wrapped_constructor(
279 &detail::construct_wrapped_class<Type, Policies, Signature>::apply
284 template<>
285 struct register_wrapped_type<detail::null_type>
287 template<class Signature, class Policies>
288 static void apply(detail::construct_rep::overload_t&, const Signature*, const Policies*) {}
292 // if the class is held by a smart pointer, we need to be able to
293 // implicitly dereference the pointer when needed.
295 template<class UnderlyingT, class HeldT>
296 struct extract_underlying_type
298 static void* extract(void* ptr)
300 HeldT& held_obj = *reinterpret_cast<HeldT*>(ptr);
301 UnderlyingT* underlying_ptr = static_cast<UnderlyingT*>(get_pointer(held_obj));
302 return underlying_ptr;
306 template<class UnderlyingT, class HeldT>
307 struct extract_underlying_const_type
309 static const void* extract(void* ptr)
311 HeldT& held_obj = *reinterpret_cast<HeldT*>(ptr);
312 const UnderlyingT* underlying_ptr = static_cast<const UnderlyingT*>(get_pointer(held_obj));
313 return underlying_ptr;
317 template<class HeldType>
318 struct internal_holder_extractor
320 typedef void*(*extractor_fun)(void*);
322 template<class T>
323 static extractor_fun apply(detail::type<T>)
325 return &detail::extract_underlying_type<T, HeldType>::extract;
329 template<>
330 struct internal_holder_extractor<detail::null_type>
332 typedef void*(*extractor_fun)(void*);
334 template<class T>
335 static extractor_fun apply(detail::type<T>)
337 return 0;
342 template<class HeldType, class ConstHolderType>
343 struct convert_holder
345 static void apply(void* holder, void* target)
347 new(target) ConstHolderType(*reinterpret_cast<HeldType*>(holder));
352 template<class HeldType>
353 struct const_converter
355 typedef void(*converter_fun)(void*, void*);
357 template<class ConstHolderType>
358 static converter_fun apply(ConstHolderType*)
360 return &detail::convert_holder<HeldType, ConstHolderType>::apply;
364 template<>
365 struct const_converter<detail::null_type>
367 typedef void(*converter_fun)(void*, void*);
369 template<class T>
370 static converter_fun apply(T*)
372 return 0;
379 template<class HeldType>
380 struct internal_const_holder_extractor
382 typedef const void*(*extractor_fun)(void*);
384 template<class T>
385 static extractor_fun apply(detail::type<T>)
387 return get_extractor(detail::type<T>(), luabind::get_const_holder(static_cast<HeldType*>(0)));
389 private:
390 template<class T, class ConstHolderType>
391 static extractor_fun get_extractor(detail::type<T>, ConstHolderType*)
393 return &detail::extract_underlying_const_type<T, ConstHolderType>::extract;
397 template<>
398 struct internal_const_holder_extractor<detail::null_type>
400 typedef const void*(*extractor_fun)(void*);
402 template<class T>
403 static extractor_fun apply(detail::type<T>)
405 return 0;
411 // this is simply a selector that returns the type_info
412 // of the held type, or invalid_type_info if we don't have
413 // a held_type
414 template<class HeldType>
415 struct internal_holder_type
417 static LUABIND_TYPE_INFO apply()
419 return LUABIND_TYPEID(HeldType);
423 template<>
424 struct internal_holder_type<detail::null_type>
426 static LUABIND_TYPE_INFO apply()
428 return LUABIND_INVALID_TYPE_INFO;
433 // this is the actual held_type constructor
434 template<class HeldType, class T>
435 struct internal_construct_holder
437 static void apply(void* target, void* raw_pointer)
439 new(target) HeldType(static_cast<T*>(raw_pointer));
443 // the following two functions are the ones that returns
444 // a pointer to a held_type_constructor, or 0 if there
445 // is no held_type
446 template<class HeldType>
447 struct holder_constructor
449 typedef void(*constructor)(void*,void*);
450 template<class T>
451 static constructor apply(detail::type<T>)
453 return &internal_construct_holder<HeldType, T>::apply;
457 template<>
458 struct holder_constructor<detail::null_type>
460 typedef void(*constructor)(void*,void*);
461 template<class T>
462 static constructor apply(detail::type<T>)
464 return 0;
468 // the following two functions are the ones that returns
469 // a pointer to a const_held_type_constructor, or 0 if there
470 // is no held_type
471 template<class HolderType>
472 struct const_holder_constructor
474 typedef void(*constructor)(void*,void*);
475 template<class T>
476 static constructor apply(detail::type<T>)
478 return get_const_holder_constructor(detail::type<T>(), luabind::get_const_holder(static_cast<HolderType*>(0)));
481 private:
483 template<class T, class ConstHolderType>
484 static constructor get_const_holder_constructor(detail::type<T>, ConstHolderType*)
486 return &internal_construct_holder<ConstHolderType, T>::apply;
490 template<>
491 struct const_holder_constructor<detail::null_type>
493 typedef void(*constructor)(void*,void*);
494 template<class T>
495 static constructor apply(detail::type<T>)
497 return 0;
503 // this is a selector that returns the size of the held_type
504 // or 0 if we don't have a held_type
505 template <class HolderType>
506 struct internal_holder_size
508 static int apply() { return get_internal_holder_size(luabind::get_const_holder(static_cast<HolderType*>(0))); }
509 private:
510 template<class ConstHolderType>
511 static int get_internal_holder_size(ConstHolderType*)
513 return max_c<sizeof(HolderType), sizeof(ConstHolderType)>::value;
517 template <>
518 struct internal_holder_size<detail::null_type>
520 static int apply() { return 0; }
524 // if we have a held type, return the destructor to it
525 // note the difference. The held_type should only be destructed (not deleted)
526 // since it's constructed in the lua userdata
527 template<class HeldType>
528 struct internal_holder_destructor
530 typedef void(*destructor_t)(void*);
531 template<class T>
532 static destructor_t apply(detail::type<T>)
534 return &detail::destruct_only_s<HeldType>::apply;
538 // if we don't have a held type, return the destructor of the raw type
539 template<>
540 struct internal_holder_destructor<detail::null_type>
542 typedef void(*destructor_t)(void*);
543 template<class T>
544 static destructor_t apply(detail::type<T>)
546 return &detail::delete_s<T>::apply;
551 // if we have a held type, return the destructor to it's const version
552 template<class HolderType>
553 struct internal_const_holder_destructor
555 typedef void(*destructor_t)(void*);
556 template<class T>
557 static destructor_t apply(detail::type<T>)
559 return const_holder_type_destructor(luabind::get_const_holder(static_cast<HolderType*>(0)));
562 private:
564 template<class ConstHolderType>
565 static destructor_t const_holder_type_destructor(ConstHolderType*)
567 return &detail::destruct_only_s<ConstHolderType>::apply;
572 // if we don't have a held type, return the destructor of the raw type
573 template<>
574 struct internal_const_holder_destructor<detail::null_type>
576 typedef void(*destructor_t)(void*);
577 template<class T>
578 static destructor_t apply(detail::type<T>)
580 return 0;
587 template<class HolderType>
588 struct get_holder_alignment
590 static int apply()
592 return internal_alignment(luabind::get_const_holder(static_cast<HolderType*>(0)));
595 private:
597 template<class ConstHolderType>
598 static int internal_alignment(ConstHolderType*)
600 return detail::max_c<boost::alignment_of<HolderType>::value
601 , boost::alignment_of<ConstHolderType>::value>::value;
605 template<>
606 struct get_holder_alignment<detail::null_type>
608 static int apply()
610 return 1;
615 } // detail
630 struct class_base: detail::scoped_object
632 protected:
634 struct base_desc
636 LUABIND_TYPE_INFO type;
637 int ptr_offset;
640 private:
642 #ifndef NDEBUG
643 bool m_cloned;
644 #endif
646 const char* m_name;
648 std::map<const char*, detail::method_rep, detail::ltstr> m_methods;
650 // datamembers, some members may be readonly, and
651 // only have a getter function
652 std::map<const char*, detail::class_rep::callback, detail::ltstr> m_getters;
653 std::map<const char*, detail::class_rep::callback, detail::ltstr> m_setters;
655 // the operators in lua
656 std::vector<detail::class_rep::operator_callback> m_operators[detail::number_of_operators];
657 std::map<const char*, int, detail::ltstr> m_static_constants;
659 std::vector<base_desc> m_bases;
660 detail::construct_rep m_constructor;
662 void(*m_destructor)(void*);
663 void(*m_const_holder_destructor)(void*);
665 void*(*m_extractor)(void*);
666 const void*(*m_const_extractor)(void*);
668 void(*m_const_converter)(void*,void*);
670 void(*m_construct_holder)(void*, void*);
671 void(*m_construct_const_holder)(void*, void*);
673 int m_holder_size;
674 int m_holder_alignment;
676 LUABIND_TYPE_INFO m_type;
677 LUABIND_TYPE_INFO m_holder_type;
678 LUABIND_TYPE_INFO m_const_holder_type;
680 #ifndef LUABIND_DONT_COPY_STRINGS
681 // the maps that contains char pointers points into
682 // this vector of strings.
683 std::vector<char*> m_strings;
684 #endif
687 public:
689 // public 'cause of enum_maker, FIX
690 void add_static_constant(const char* name, int val)
692 m_static_constants[name] = val;
695 protected:
697 mutable std::vector<detail::scoped_object*> m_children;
699 void init(LUABIND_TYPE_INFO type
700 , LUABIND_TYPE_INFO holder_type
701 , void*(*extractor)(void*)
702 , const void*(*const_extractor)(void*)
703 , void(*const_converter)(void*,void*)
704 , void(*holder_constructor)(void*,void*)
705 , void(*const_holder_constructor)(void*,void*)
706 , void(*destructor)(void*)
707 , void(*const_holder_destructor)(void*)
708 , int holder_size
709 , int holder_alignment)
711 m_type = type;
712 m_holder_type = holder_type;
713 m_extractor = extractor;
714 m_const_extractor = const_extractor;
715 m_const_converter = const_converter;
716 m_construct_holder = holder_constructor;
717 m_construct_const_holder = const_holder_constructor;
718 m_destructor = destructor;
719 m_const_holder_destructor = const_holder_destructor;
720 m_holder_size = holder_size;
721 m_holder_alignment = holder_alignment;
724 template<class T>
725 void set_const_holder_type(T*)
727 m_const_holder_type = LUABIND_TYPEID(T);
730 inline void add_getter(const char* name, const boost::function2<int, lua_State*, int>& g)
732 detail::class_rep::callback c;
733 c.func = g;
734 c.pointer_offset = 0;
735 #ifndef LUABIND_DONT_COPY_STRINGS
736 m_strings.push_back(detail::dup_string(name));
737 m_getters[m_strings.back()] = c;
738 #else
739 m_getters[name] = c;
740 #endif
743 inline void add_setter(const char* name, const boost::function2<int, lua_State*, int>& s)
745 detail::class_rep::callback c;
746 c.func = s;
747 c.pointer_offset = 0;
748 #ifndef LUABIND_DONT_COPY_STRINGS
749 m_strings.push_back(detail::dup_string(name));
750 m_setters[m_strings.back()] = c;
751 #else
752 m_setters[name] = c;
753 #endif
756 void add_base(const base_desc& b)
758 m_bases.push_back(b);
761 public:
763 void add_constructor(const detail::construct_rep::overload_t& o)
765 m_constructor.overloads.push_back(o);
768 void add_method(const char* name, const detail::overload_rep& o)
770 #ifdef LUABIND_DONT_COPY_STRINGS
771 detail::method_rep& method = m_methods[name];
772 method.name = name;
773 #else
774 m_strings.push_back(detail::dup_string(name));
775 detail::method_rep& method = m_methods[m_strings.back()];
776 method.name = m_strings.back();
777 #endif
778 method.add_overload(o);
779 method.crep = 0;
782 #ifndef LUABIND_NO_ERROR_CHECKING
783 inline void add_operator(int op_id, int(*func)(lua_State*), int(*matcher)(lua_State*), void(*sig)(lua_State*, std::string&), int arity)
784 #else
785 inline void add_operator(int op_id, int(*func)(lua_State*), int(*matcher)(lua_State*), int arity)
786 #endif
788 detail::class_rep::operator_callback o;
789 o.set_fun(func);
790 o.set_match_fun(matcher);
791 o.set_arity(arity);
793 #ifndef LUABIND_NO_ERROR_CHECKING
795 o.set_sig_fun(sig);
797 #endif
798 m_operators[op_id].push_back(o);
807 const char* name() const { return m_name; }
809 class_base(const char* name)
811 #ifndef LUABIND_DONT_COPY_STRINGS
812 m_strings.push_back(detail::dup_string(name));
813 m_name = m_strings.back();
814 #else
815 m_name = name;
816 #endif
818 #ifndef NDEBUG
819 m_cloned = false;
820 #endif
823 virtual ~class_base()
825 for (std::vector<detail::scoped_object*>::iterator
826 i = m_children.begin(); i != m_children.end(); ++i)
827 delete *i;
829 // if we are copying strings, we have to destroy them too
830 #ifndef LUABIND_DONT_COPY_STRINGS
831 for (std::vector<char*>::iterator i = m_strings.begin(); i != m_strings.end(); ++i)
832 delete[] *i;
833 #endif
836 // pushes the class_rep on the lua stack
837 virtual void commit(lua_State* L)
839 assert(!m_cloned && "class already commited");
841 detail::getref(L, scope_stack::top(L));
842 lua_pushstring(L, m_name);
844 detail::class_rep* crep;
846 detail::class_registry* r = detail::class_registry::get_registry(L);
847 // create a class_rep structure for this class.
848 // allocate it within lua to let lua collect it on
849 // lua_close(). This is better than allocating it
850 // as a static, since it will then be destructed
851 // when the program exits instead.
852 // warning: we assume that lua will not
853 // move the userdata memory.
854 lua_newuserdata(L, sizeof(detail::class_rep));
855 crep = reinterpret_cast<detail::class_rep*>(lua_touserdata(L, -1));
857 new(crep) detail::class_rep( m_type
858 , m_name
860 , m_destructor
861 , m_const_holder_destructor
862 , m_holder_type
863 , m_const_holder_type
864 , m_extractor
865 , m_const_extractor
866 , m_const_converter
867 , m_construct_holder
868 , m_construct_const_holder
869 , m_holder_size
870 , m_holder_alignment);
872 // register this new type in the class registry
873 r->add_class(m_type, crep);
874 if (!(LUABIND_TYPE_INFO_EQUAL(m_holder_type, LUABIND_INVALID_TYPE_INFO)))
876 // if we have a held type
877 // we have to register it in the class-table
878 // but only for the base class, if it already
879 // exists, we don't have to register it
880 detail::class_rep* c = r->find_class(m_holder_type);
881 if (c == 0)
883 r->add_class(m_holder_type, crep);
884 r->add_class(m_const_holder_type, crep);
888 // constructors
889 m_constructor.swap(crep->m_constructor);
891 #ifndef LUABIND_DONT_COPY_STRINGS
892 assert(crep->m_strings.empty() && "Internal error");
893 std::swap(crep->m_strings, m_strings);
894 #endif
896 std::swap(crep->m_getters, m_getters);
897 std::swap(crep->m_setters, m_setters);
899 for(int i = 0; i < detail::number_of_operators; ++i)
900 std::swap(crep->m_operators[i], m_operators[i]);
902 std::swap(crep->m_static_constants, m_static_constants);
904 // here!
905 // crep->m_methods = m_methods;
907 for (std::vector<base_desc>::iterator i = m_bases.begin();
908 i != m_bases.end();
909 ++i)
911 detail::class_registry* r = detail::class_registry::get_registry(L);
913 // the baseclass' class_rep structure
914 detail::class_rep* bcrep = r->find_class(i->type);
916 detail::class_rep::base_info base;
917 base.pointer_offset = i->ptr_offset;
918 base.base = bcrep;
920 crep->add_base_class(base);
922 typedef std::map<const char*, detail::method_rep, detail::ltstr> methods_t;
924 for (methods_t::const_iterator i
925 = bcrep->m_methods.begin()
926 ; i != bcrep->m_methods.end()
927 ; ++i)
929 detail::method_rep& m = m_methods[i->first];
931 typedef std::vector<detail::overload_rep> overloads_t;
933 for (overloads_t::const_iterator j
934 = i->second.overloads().begin()
935 ; j != i->second.overloads().end()
936 ; ++j)
938 detail::overload_rep o = *j;
939 o.add_offset(base.pointer_offset);
940 m.add_overload(o);
944 // copy base class table
945 detail::getref(L, crep->table_ref());
946 detail::getref(L, bcrep->table_ref());
947 lua_pushnil(L);
949 while (lua_next(L, -2))
951 lua_pushvalue(L, -2); // copy key
952 lua_insert(L, -2);
953 lua_settable(L, -5);
956 lua_pop(L, 2);
959 crep->m_methods = m_methods;
961 for (std::map<const char*, detail::method_rep, detail::ltstr>::iterator i
962 = crep->m_methods.begin(); i != crep->m_methods.end(); ++i)
964 i->second.crep = crep;
967 // add methods
968 for (std::map<const char*, detail::method_rep, detail::ltstr>::iterator i
969 = m_methods.begin(); i != m_methods.end(); ++i)
971 detail::getref(L, crep->table_ref());
972 lua_pushstring(L, i->first);
973 lua_pushnil(L);
974 lua_settable(L, -3);
975 lua_pop(L, 1);
977 crep->add_method(L, i->first, crep->m_methods[i->first]);
978 i->second.crep = crep;
981 m_methods.clear();
983 lua_settable(L, -3);
984 lua_pop(L, 1);
988 // destructive copy
989 virtual luabind::detail::scoped_object* clone()
991 assert(m_cloned == false);
993 #ifndef NDEBUG
994 m_cloned = true;
995 #endif
997 class_base* ret = new class_base(m_name);
999 std::swap(ret->m_getters, m_getters);
1000 std::swap(ret->m_setters, m_setters);
1002 for(int i = 0; i < detail::number_of_operators; ++i)
1003 std::swap(ret->m_operators[i], m_operators[i]);
1005 std::swap(ret->m_static_constants, m_static_constants);
1007 ret->init(m_type
1008 , m_holder_type
1009 , m_extractor
1010 , m_const_extractor
1011 , m_const_converter
1012 , m_construct_holder
1013 , m_construct_const_holder
1014 , m_destructor
1015 , m_const_holder_destructor
1016 , m_holder_size
1017 , m_holder_alignment);
1019 ret->m_const_holder_type = m_const_holder_type;
1021 ret->m_bases.swap(m_bases);
1022 ret->m_methods.swap(m_methods);
1023 m_constructor.swap(ret->m_constructor);
1025 ret->m_name = m_name;
1027 #ifndef LUABIND_DONT_COPY_STRINGS
1028 std::swap(ret->m_strings, m_strings);
1029 #endif
1031 m_children.swap(ret->m_children);
1033 return ret;
1037 namespace detail {
1039 struct class_registration;
1041 struct class_base : detail::scope
1043 public:
1044 class_base(char const* name);
1046 struct base_desc
1048 LUABIND_TYPE_INFO type;
1049 int ptr_offset;
1052 void init(
1053 LUABIND_TYPE_INFO type
1054 , LUABIND_TYPE_INFO holder_type
1055 , LUABIND_TYPE_INFO const_holder_type
1056 , void*(*extractor)(void*)
1057 , const void*(*const_extractor)(void*)
1058 , void(*const_converter)(void*,void*)
1059 , void(*holder_constructor)(void*,void*)
1060 , void(*const_holder_constructor)(void*,void*)
1061 , void(*destructor)(void*)
1062 , void(*const_holder_destructor)(void*)
1063 , int holder_size
1064 , int holder_alignment);
1066 void add_getter(
1067 const char* name
1068 , const boost::function2<int, lua_State*, int>& g);
1070 #ifdef LUABIND_NO_ERROR_CHECKING
1071 void class_base::add_setter(
1072 const char* name
1073 , const boost::function2<int, lua_State*, int>& s);
1074 #else
1075 void class_base::add_setter(
1076 const char* name
1077 , const boost::function2<int, lua_State*, int>& s
1078 , int (*match)(lua_State*, int)
1079 , void (*get_sig_ptr)(lua_State*, std::string&));
1080 #endif
1082 void add_base(const base_desc& b);
1083 void add_constructor(const detail::construct_rep::overload_t& o);
1084 void add_method(const char* name, const detail::overload_rep& o);
1086 #ifndef LUABIND_NO_ERROR_CHECKING
1087 void add_operator(
1088 int op_id
1089 , int(*func)(lua_State*)
1090 , int(*matcher)(lua_State*)
1091 , void(*sig)(lua_State*
1092 , std::string&)
1093 , int arity);
1094 #else
1095 void add_operator(
1096 int op_id
1097 , int(*func)(lua_State*)
1098 , int(*matcher)(lua_State*)
1099 , int arity);
1100 #endif
1102 const char* name() const;
1104 void add_static_constant(const char* name, int val);
1106 private:
1107 class_registration* m_registration;
1110 } // namespace detail
1112 // registers a class in the lua environment
1113 template<class T, class X1, class X2, class X3>
1114 struct class_: detail::class_base
1116 typedef class_<T, X1, X2, X3> self_t;
1118 lua_State* m_L;
1120 private:
1122 template<class A, class B, class C, class D>
1123 class_(const class_<A,B,C,D>&);
1125 public:
1127 // WrappedType MUST inherit from T
1128 typedef typename detail::extract_parameter<
1129 boost::mpl::vector3<X1,X2,X3>
1130 , boost::is_base_and_derived<T, boost::mpl::_>
1131 /* , boost::mpl::not_<
1132 boost::mpl::or_<
1133 detail::is_bases<boost::mpl::_>
1134 , boost::is_base_and_derived<boost::mpl::_, T>
1137 , detail::null_type
1138 >::type WrappedType;
1140 typedef typename detail::extract_parameter<
1141 boost::mpl::list3<X1,X2,X3>
1142 , boost::mpl::not_<
1143 boost::mpl::or_<
1144 boost::mpl::or_<
1145 detail::is_bases<boost::mpl::_>
1146 , boost::is_base_and_derived<boost::mpl::_, T>
1148 , boost::is_base_and_derived<T, boost::mpl::_>
1151 , detail::null_type
1152 >::type HeldType;
1154 template<class To>
1155 void register_downcast(boost::mpl::true_, detail::type<To>* = 0)
1156 { boost::langbinding::register_conversion<To, T>(true); }
1158 template<class To>
1159 void register_downcast(boost::mpl::false_, detail::type<To>* = 0)
1162 // this function generates conversion information
1163 // in the given class_rep structure. It will be able
1164 // to implicitly cast to the given template type
1165 template<class To>
1166 void gen_base_info(detail::type<To>)
1168 // boost::langbinding::register_dynamic_id<To>();
1169 // boost::langbinding::register_conversion<T, To>(false);
1171 // register_downcast<To>(boost::mpl::bool_<boost::is_polymorphic<To>::value>());
1173 // fist, make sure the given base class is registered.
1174 // if it's not registered we can't push it's lua table onto
1175 // the stack because it doesn't have a table
1177 // try to cast this type to the base type and remember
1178 // the pointer offset. For multiple inheritance the pointer
1179 // may change when casting. Since we need to be able to
1180 // cast we need this pointer offset.
1181 // store the information in this class' base class-vector
1182 base_desc base;
1183 base.type = LUABIND_TYPEID(To);
1184 base.ptr_offset = detail::ptr_offset(detail::type<T>(), detail::type<To>());
1185 add_base(base);
1188 void gen_base_info(detail::type<detail::null_type>)
1191 #define LUABIND_GEN_BASE_INFO(z, n, text) gen_base_info(detail::type<B##n>());
1193 template<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_BASES, class B)>
1194 void generate_baseclass_list(detail::type<bases<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_BASES, B)> >)
1196 BOOST_PP_REPEAT(LUABIND_MAX_BASES, LUABIND_GEN_BASE_INFO, _)
1199 #undef LUABIND_GEN_BASE_INFO
1201 // this is the internal version of def() it is run from both overloads
1202 // of def. It has two versions, one where a contstructor is registered
1203 // and one where a function is registered
1204 template<class Policies>
1205 struct internal_def_s
1207 template<class F>
1208 static void apply(const char* name, F f, detail::class_base* c)
1210 // std::cout << "HeldType2: " << typeid(HeldType).name() << "\n";
1212 detail::overload_rep o(f, static_cast<Policies*>(0));
1214 typedef LUABIND_MSVC_TYPENAME detail::function_callback_s<HeldType,T,F,Policies>::type call_t;
1216 o.set_match_fun(&detail::match_function_callback_s<T,F,Policies>::apply);
1217 o.call_fun = boost::bind<int>(call_t(f), _1, _2);
1219 #ifndef LUABIND_NO_ERROR_CHECKING
1221 o.set_sig_fun(&detail::get_member_signature<F>::apply);
1223 #endif
1225 c->add_method(name, o);
1228 template<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, class A)>
1229 static void apply(constructor<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, A)>, detail::class_base* c)
1231 // std::cout << "HeldType2: " << typeid(HeldType).name() << "\n";
1233 detail::construct_rep::overload_t o;
1235 o.set_constructor(
1236 &detail::construct_class<
1238 ,Policies
1239 ,constructor<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, A)>
1240 >::apply
1243 // if we have a WrappedType, we have to register it's constructor
1244 // but if it's null_type (no WrappedType) we should not register it
1245 detail::register_wrapped_type<WrappedType>::apply(o,
1246 static_cast<const constructor<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, A)>*>(0),
1247 static_cast<const Policies*>(0));
1250 o.set_match_fun(
1251 &detail::constructor_match<
1252 constructor<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, A)>
1254 ,Policies
1255 >::apply);
1257 #ifndef LUABIND_NO_ERROR_CHECKING
1259 o.set_sig_fun(&detail::get_signature<constructor<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, A)> >::apply);
1261 #endif
1263 typedef constructor<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, A)> con_t;
1265 o.set_arity(detail::calc_arity<con_t::arity>::apply(con_t(), static_cast<Policies*>(0)));
1267 c->add_constructor(o);
1271 class_(lua_State* L, const char* name): class_base(name), m_L(L) { init(); }
1272 class_(const char* name): class_base(name), m_L(0) { init(); }
1274 ~class_()
1276 /* if (m_L != 0)
1278 scope::init(m_L);
1279 lua_pushvalue(m_L, LUA_GLOBALSINDEX);
1280 scope_stack::push(m_L);
1281 commit(m_L);
1282 scope_stack::pop(m_L);
1286 template<class F>
1287 class_& def(const char* name, F f)
1289 internal_def_s<detail::null_type>::apply(name, f, this);
1290 return *this;
1293 template<class F, class Policies>
1294 class_& def(const char* name, F f, const Policies&)
1296 internal_def_s<Policies>::apply(name, f, this);
1297 return *this;
1300 template<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, class A)>
1301 class_& def(constructor<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, A)> sig)
1303 internal_def_s<detail::null_type>::apply(sig, this);
1304 return *this;
1307 template<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, class A), class Policies>
1308 class_& def(constructor<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, A)> sig, const Policies& policies)
1310 internal_def_s<Policies>::apply(sig, this);
1311 return *this;
1314 template<class Getter>
1315 class_& property(const char* name, Getter g)
1317 add_getter(name, boost::bind<int>(detail::get_caller<T, Getter, detail::null_type>(), _1, _2, g));
1318 return *this;
1321 template<class Getter, class MaybeSetter>
1322 class_& property(const char* name, Getter g, MaybeSetter s)
1324 return property_impl(name, g, s, boost::mpl::bool_<detail::is_policy_cons<MaybeSetter>::value>());
1327 template<class Getter, class Setter, class GetPolicies>
1328 class_& property(const char* name, Getter g, Setter s, const GetPolicies& get_policies)
1330 add_getter(name, boost::bind<int>(detail::get_caller<T, Getter, GetPolicies>(get_policies), _1, _2, g));
1331 #ifndef LUABIND_NO_ERROR_CHECKING
1332 add_setter(
1333 name
1334 , boost::bind<int>(detail::set_caller<T, Setter, detail::null_type>(), _1, _2, s)
1335 , detail::gen_set_matcher((Setter)0, (detail::null_type*)0)
1336 , &detail::get_member_signature<Setter>::apply);
1337 #else
1338 add_setter(
1339 name
1340 , boost::bind<int>(detail::set_caller<T, Setter, detail::null_type>(), _1, _2, s));
1341 #endif
1342 return *this;
1345 template<class Getter, class Setter, class GetPolicies, class SetPolicies>
1346 class_& property(const char* name
1347 , Getter g, Setter s
1348 , const GetPolicies& get_policies
1349 , const SetPolicies& set_policies)
1351 add_getter(name, boost::bind<int>(detail::get_caller<T, Getter, GetPolicies>(get_policies), _1, _2, g));
1352 #ifndef LUABIND_NO_ERROR_CHECKING
1353 add_setter(
1354 name
1355 , boost::bind<int>(detail::set_caller<T, Setter, SetPolicies>(), _1, _2, s)
1356 , detail::gen_set_matcher((Setter)0, (SetPolicies*)0)
1357 , &detail::get_member_signature<Setter>::apply);
1358 #else
1359 add_setter(name, boost::bind<int>(detail::set_caller<T, Setter, SetPolicies>(set_policies), _1, _2, s));
1360 #endif
1361 return *this;
1364 template<class D>
1365 class_& def_readonly(const char* name, D T::*member_ptr)
1367 add_getter(name, boost::bind<int>(detail::auto_get<T,D,detail::null_type>(), _1, _2, member_ptr));
1368 return *this;
1371 template<class D, class Policies>
1372 class_& def_readonly(const char* name, D T::*member_ptr, const Policies& policies)
1374 add_getter(name, boost::bind<int>(detail::auto_get<T,D,Policies>(policies), _1, _2, member_ptr));
1375 return *this;
1378 template<class D>
1379 class_& def_readwrite(const char* name, D T::*member_ptr)
1381 add_getter(name, boost::bind<int>(detail::auto_get<T,D,detail::null_type>(), _1, _2, member_ptr));
1382 #ifndef LUABIND_NO_ERROR_CHECKING
1383 add_setter(
1384 name
1385 , boost::bind<int>(detail::auto_set<T,D,detail::null_type>(), _1, _2, member_ptr)
1386 , &detail::set_matcher<D, detail::null_type>::apply
1387 , &detail::get_setter_signature<D>::apply);
1388 #else
1389 add_setter(name, boost::bind<int>(detail::auto_set<T,D,detail::null_type>(), _1, _2, member_ptr));
1390 #endif
1391 return *this;
1394 template<class D, class GetPolicies>
1395 class_& def_readwrite(const char* name, D T::*member_ptr, const GetPolicies& get_policies)
1397 add_getter(name, boost::bind<int>(detail::auto_get<T,D,GetPolicies>(get_policies), _1, _2, member_ptr));
1398 #ifndef LUABIND_NO_ERROR_CHECKING
1399 add_setter(
1400 name
1401 , boost::bind<int>(detail::auto_set<T,D,detail::null_type>(), _1, _2, member_ptr)
1402 , &detail::set_matcher<D, detail::null_type>::apply
1403 , &detail::get_setter_signature<D>::apply);
1404 #else
1405 add_setter(name, boost::bind<int>(detail::auto_set<T,D,detail::null_type>(), _1, _2, member_ptr));
1406 #endif
1407 return *this;
1410 template<class D, class GetPolicies, class SetPolicies>
1411 class_& def_readwrite(const char* name, D T::*member_ptr, const GetPolicies& get_policies, const SetPolicies& set_policies)
1413 add_getter(name, boost::bind<int>(detail::auto_get<T,D,GetPolicies>(get_policies), _1, _2, member_ptr));
1414 #ifndef LUABIND_NO_ERROR_CHECKING
1415 add_setter(
1416 name
1417 , boost::bind<int>(detail::auto_set<T,D,SetPolicies>(), _1, _2, member_ptr)
1418 , &detail::set_matcher<D, SetPolicies>::apply
1419 , &detail::get_setter_signature<D>::apply);
1420 #else
1421 add_setter(name, boost::bind<int>(detail::auto_set<T,D,SetPolicies>(set_policies), _1, _2, member_ptr));
1422 #endif
1423 return *this;
1426 template<class op_id, class Left, class Right, class Policies>
1427 class_& def(detail::operator_<op_id, Left, Right>, const Policies& policies)
1429 typedef typename detail::operator_unwrapper<Policies, op_id, T, Left, Right> op_type;
1430 #ifndef LUABIND_NO_ERROR_CHECKING
1431 add_operator(op_type::get_id()
1432 , &op_type::execute
1433 , &op_type::match
1434 , &detail::get_signature<constructor<typename op_type::left_t, typename op_type::right_t> >::apply
1435 , detail::is_unary(op_type::get_id()) ? 1 : 2);
1436 #else
1437 add_operator(op_type::get_id()
1438 , &op_type::execute
1439 , &op_type::match
1440 , detail::is_unary(op_type::get_id()) ? 1 : 2);
1441 #endif
1442 return *this;
1445 template<class op_id, class Left, class Right>
1446 class_& def(detail::operator_<op_id, Left, Right>)
1448 typedef typename detail::operator_unwrapper<detail::null_type, op_id, T, Left, Right> op_type;
1450 #ifndef LUABIND_NO_ERROR_CHECKING
1451 add_operator(op_type::get_id()
1452 , &op_type::execute
1453 , &op_type::match
1454 , &detail::get_signature<constructor<LUABIND_MSVC_TYPENAME op_type::left_t, LUABIND_MSVC_TYPENAME op_type::right_t> >::apply
1455 , detail::is_unary(op_type::get_id()) ? 1 : 2);
1456 #else
1457 add_operator(op_type::get_id()
1458 , &op_type::execute
1459 , &op_type::match
1460 , detail::is_unary(op_type::get_id()) ? 1 : 2);
1461 #endif
1462 return *this;
1465 template<class Signature, bool Constant>
1466 class_& def(detail::application_operator<Signature, Constant>*)
1468 typedef detail::application_operator<Signature, Constant, detail::null_type> op_t;
1470 int arity = detail::calc_arity<Signature::arity>::apply(Signature(), static_cast<detail::null_type*>(0));
1472 #ifndef LUABIND_NO_ERROR_CHECKING
1473 add_operator(detail::op_call, &op_t::template apply<T>::execute, &op_t::match, &detail::get_signature<Signature>::apply, arity + 1);
1474 #else
1475 add_operator(detail::op_call, &op_t::template apply<T>::execute, &op_t::match, arity + 1);
1476 #endif
1478 return *this;
1481 template<class Signature, bool Constant, class Policies>
1482 class_& def(detail::application_operator<Signature, Constant>*, const Policies& policies)
1484 typedef detail::application_operator<Signature, Constant, Policies> op_t;
1486 int arity = detail::calc_arity<Signature::arity>::apply(Signature(), static_cast<Policies*>(0));
1488 #ifndef LUABIND_NO_ERROR_CHECKING
1489 add_operator(detail::op_call, &op_t::template apply<T>::execute, &op_t::match, &detail::get_signature<Signature>::apply, arity + 1);
1490 #else
1491 add_operator(detail::op_call, &op_t::template apply<T>::execute, &op_t::match, arity + 1);
1492 #endif
1494 return *this;
1497 detail::enum_maker<self_t> enum_(const char*)
1499 return detail::enum_maker<self_t>(*this);
1502 private:
1504 void init()
1506 typedef typename detail::extract_parameter<
1507 boost::mpl::list3<X1,X2,X3>
1508 , boost::mpl::or_<
1509 detail::is_bases<boost::mpl::_>
1510 , boost::is_base_and_derived<boost::mpl::_, T>
1512 , no_bases
1513 >::type bases_t;
1515 typedef typename
1516 boost::mpl::if_<detail::is_bases<bases_t>
1517 , bases_t
1518 , bases<bases_t>
1519 >::type Base;
1521 class_base::init(LUABIND_TYPEID(T)
1522 , detail::internal_holder_type<HeldType>::apply()
1523 , detail::pointee_typeid(
1524 get_const_holder(static_cast<HeldType*>(0)))
1525 , detail::internal_holder_extractor<HeldType>::apply(detail::type<T>())
1526 , detail::internal_const_holder_extractor<HeldType>::apply(detail::type<T>())
1527 , detail::const_converter<HeldType>::apply(
1528 luabind::get_const_holder((HeldType*)0))
1529 , detail::holder_constructor<HeldType>::apply(detail::type<T>())
1530 , detail::const_holder_constructor<HeldType>::apply(detail::type<T>())
1531 , detail::internal_holder_destructor<HeldType>::apply(detail::type<T>())
1532 , detail::internal_const_holder_destructor<HeldType>::apply(detail::type<T>())
1533 , detail::internal_holder_size<HeldType>::apply()
1534 , detail::get_holder_alignment<HeldType>::apply());
1536 generate_baseclass_list(detail::type<Base>());
1539 template<class Getter, class GetPolicies>
1540 class_& property_impl(const char* name,
1541 Getter g,
1542 GetPolicies policies,
1543 boost::mpl::bool_<true>)
1545 add_getter(name, boost::bind<int>(detail::get_caller<T,Getter,GetPolicies>(policies), _1, _2, g));
1546 return *this;
1549 template<class Getter, class Setter>
1550 class_& property_impl(const char* name,
1551 Getter g,
1552 Setter s,
1553 boost::mpl::bool_<false>)
1555 add_getter(name, boost::bind<int>(detail::get_caller<T,Getter,detail::null_type>(), _1, _2, g));
1556 #ifndef LUABIND_NO_ERROR_CHECKING
1557 add_setter(
1558 name
1559 , boost::bind<int>(detail::set_caller<T, Setter, detail::null_type>(), _1, _2, s)
1560 , detail::gen_set_matcher((Setter)0, (detail::null_type*)0)
1561 , &detail::get_member_signature<Setter>::apply);
1562 #else
1563 add_setter(name, boost::bind<int>(detail::set_caller<T,Setter,detail::null_type>(), _1, _2, s));
1564 #endif
1565 return *this;
1571 #endif // LUABIND_CLASS_HPP_INCLUDED