fixed vc7.1 issues
[luabind.git] / luabind / object.hpp
blob271511c74caeff309dd3b04b1be8dfc84eb98ca7
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.
23 #if !BOOST_PP_IS_ITERATING
25 #ifndef LUABIND_OBJECT_HPP_INCLUDED
26 #define LUABIND_OBJECT_HPP_INCLUDED
28 #include <iterator>
30 #include <luabind/config.hpp>
31 #include <luabind/detail/error.hpp>
33 #include <boost/preprocessor/repeat.hpp>
34 #include <boost/preprocessor/iteration/iterate.hpp>
35 #include <boost/preprocessor/repetition/enum.hpp>
36 #include <boost/preprocessor/repetition/enum_params.hpp>
37 #include <boost/preprocessor/repetition/enum_binary_params.hpp>
38 #include <boost/tuple/tuple.hpp>
40 namespace luabind
42 // below are some considerations that haven't been implemented
45 // object might need to be able to store values temporarily
46 // without knowing about a lua_State.
48 // globals["f"] = function(&f);
50 // Creates the need for this, since function() doesn't know
51 // about the state and thus can't return a fully initialized
52 // object.
54 // Current solution is to allow for objects to store a pointer
55 // to a commiter-object. This object has a virtual method which
56 // converts it's value to the lua_State.
58 // This has some serious issues. For example, how would
59 // two 'pseude-initialized' objects be able to compare?
61 // Perhaps attempting to perform operations on non-intialised
62 // objects could throw?
63 //
64 // Perhaps we could perform some not-so-smart comparisions? like:
66 // template<class T>
67 // struct commiter : base_commiter
68 // {
69 // commiter(const T& v): val(v), base_commiter(typeid(T)) {}
71 // virtual bool compare(void* rhs)
72 // {
73 // T* other = static_cast<T*>(rhs);
74 // return val == *other;
75 // }
77 // T val;
78 // };
80 // This would at least allow for the most intuitive use.. like:
82 // object a = 5;
83 // object b = 5;
85 // return a == b;
87 // However, comparing an initialized object with a non-initialized
88 // would always return false. Is this ok? Better to disallow it?
90 // the current implementation does not have commiters, all objects
91 // knows about the lua_State* or is uninitialized.
93 class object;
95 namespace detail
97 class proxy_object;
98 class proxy_raw_object;
99 class proxy_array_object;
101 template<class T>
102 void convert_to_lua(lua_State*, const T&);
104 template<int Index, class T, class Policies>
105 void convert_to_lua_p(lua_State*, const T&, const Policies&);
107 template<int Index>
108 struct push_args_from_tuple
110 template<class H, class T, class Policies>
111 inline static void apply(lua_State* L, const boost::tuples::cons<H, T>& x, const Policies& p)
113 convert_to_lua_p<Index>(L, *x.get_head(), p);
114 push_args_from_tuple<Index+1>::apply(L, x.get_tail(), p);
117 template<class H, class T>
118 inline static void apply(lua_State* L, const boost::tuples::cons<H, T>& x)
120 convert_to_lua(L, *x.get_head());
121 push_args_from_tuple<Index+1>::apply(L, x.get_tail());
124 template<class Policies>
125 inline static void apply(lua_State*, const boost::tuples::null_type&, const Policies&) {};
127 inline static void apply(lua_State*, const boost::tuples::null_type&) {};
131 template<class Tuple>
132 class proxy_caller
134 friend class luabind::object;
135 public:
137 proxy_caller(luabind::object* o, const Tuple args)
138 : m_obj(o)
139 , m_args(args)
140 , m_called(false)
144 proxy_caller(const detail::proxy_caller<Tuple>& rhs)
145 : m_obj(rhs.m_obj)
146 , m_args(rhs.m_args)
147 , m_called(rhs.m_called)
149 rhs.m_called = true;
152 ~proxy_caller();
153 operator luabind::object();
155 #if defined(BOOST_MSVC) && (BOOST_MSVC <= 1300)
156 #define LUABIND_SEMICOLON
157 #else
158 #define LUABIND_SEMICOLON ;
159 #endif
161 template<class Policies>
162 luabind::object operator[](const Policies& p) LUABIND_SEMICOLON
163 #if defined(BOOST_MSVC) && (BOOST_MSVC <= 1300)
165 m_called = true;
166 lua_State* L = m_obj->lua_state();
167 m_obj->pushvalue();
168 detail::push_args_from_tuple<1>::apply(L, m_args, p);
169 if (lua_pcall(L, boost::tuples::length<Tuple>::value, 1, 0))
171 #ifndef LUABIND_NO_EXCEPTIONS
172 throw error(L);
173 #else
174 error_callback_fun e = detail::error_callback::get().err;
175 if (e) e(L);
177 assert(0 && "the lua function threw an error and exceptions are disabled."
178 "if you want to handle this error use luabind::set_error_callback()");
179 std::terminate();
180 #endif
182 int ref = detail::ref(L);
183 return luabind::object(m_obj->lua_state(), ref, true/*luabind::object::reference()*/);
185 #endif
188 #undef LUABIND_SEMICOLON
189 private:
191 luabind::object* m_obj;
192 Tuple m_args;
193 mutable bool m_called;
199 struct stack_pop
201 stack_pop(lua_State* L, int n)
202 : m_state(L)
203 , m_n(n)
207 ~stack_pop()
209 lua_pop(m_state, m_n);
212 private:
214 lua_State* m_state;
215 int m_n;
222 class proxy_object
224 friend class luabind::object;
225 friend class luabind::detail::proxy_array_object;
226 friend class luabind::detail::proxy_raw_object;
227 // template<class T> friend T object_cast(const proxy_object& obj);
228 public:
230 template<class T>
231 proxy_object& operator=(const T& val)
233 //std::cout << "proxy assigment\n";
234 lua_State* L = m_obj->m_state;
235 m_obj->pushvalue();
236 detail::getref(L, m_key_ref);
237 detail::convert_to_lua(L, val);
238 lua_settable(L, -3);
239 // pop table
240 lua_pop(L, 1);
241 return *this;
244 proxy_object& operator=(const object& p);
245 proxy_object& operator=(const proxy_object& p);
246 proxy_object& operator=(const proxy_raw_object& p);
247 proxy_object& operator=(const proxy_array_object& p);
249 void swap(const proxy_object& rhs);
251 operator luabind::object();
253 int type() const
255 pushvalue();
256 detail::stack_pop p(lua_state(), 1);
257 return lua_type(lua_state(), -1);
260 #define LUABIND_PROXY_RAW_AT_BODY \
262 lua_State* L = lua_state(); \
263 pushvalue(); \
264 detail::convert_to_lua(L, key); \
265 lua_rawget(L, -2); \
266 int ref = detail::ref(L); \
267 lua_pop(L, 1); \
268 return object(L, ref, true); \
271 #if defined(BOOST_MSVC) && (BOOST_MSVC <= 1300)
272 template<class T>
273 inline object raw_at(const T& key)
274 LUABIND_PROXY_RAW_AT_BODY
275 #else
276 template<class T>
277 inline object raw_at(const T& key);
278 #endif
280 #define LUABIND_PROXY_AT_BODY \
282 lua_State* L = lua_state(); \
283 pushvalue(); \
284 detail::convert_to_lua(L, key); \
285 lua_gettable(L, -2); \
286 int ref = detail::ref(L); \
287 lua_pop(L, 1); \
288 return object(L, ref, true); \
291 #if defined(BOOST_MSVC) && (BOOST_MSVC <= 1300)
292 template<class T>
293 inline object at(const T& key)
294 LUABIND_PROXY_AT_BODY
295 #else
296 template<class T>
297 inline object at(const T& key);
298 #endif
300 inline bool is_valid() const { return true; }
301 lua_State* lua_state() const;
302 void pushvalue() const;
303 void set() const;
305 // this is a safe substitute for an implicit converter to bool
306 typedef void (proxy_object::*member_ptr)() const;
307 operator member_ptr() const
309 if (is_valid()) return &proxy_object::dummy;
310 return 0;
313 private:
315 void dummy() const {}
317 proxy_object(luabind::object* o, int key)
318 : m_obj(o)
319 , m_key_ref(key)
323 luabind::object* m_obj;
324 int m_key_ref;
329 class proxy_raw_object
331 friend class luabind::object;
332 friend class luabind::detail::proxy_array_object;
333 friend class luabind::detail::proxy_object;
334 // template<class T> friend T luabind::object_cast(const proxy_object& obj);
335 public:
337 template<class T>
338 proxy_raw_object& operator=(const T& val)
340 //std::cout << "proxy assigment\n";
341 lua_State* L = m_obj->m_state;
342 m_obj->pushvalue();
343 detail::getref(L, m_key_ref);
344 detail::convert_to_lua(L, val);
345 lua_rawset(L, -3);
346 // pop table
347 lua_pop(L, 1);
348 return *this;
351 proxy_raw_object& operator=(const object& p);
352 proxy_raw_object& operator=(const proxy_object& p);
353 proxy_raw_object& operator=(const proxy_raw_object& p);
354 proxy_raw_object& operator=(const proxy_array_object& p);
355 void swap(const proxy_raw_object& rhs);
357 operator luabind::object();
359 int type() const
361 pushvalue();
362 detail::stack_pop p(lua_state(), 1);
363 return lua_type(lua_state(), -1);
366 #if defined(BOOST_MSVC) && (BOOST_MSVC <= 1300)
367 template<class T>
368 inline object raw_at(const T& key)
369 LUABIND_PROXY_RAW_AT_BODY
370 #else
371 template<class T>
372 inline object raw_at(const T& key);
373 #endif
375 #if defined(BOOST_MSVC) && (BOOST_MSVC <= 1300)
376 template<class T>
377 inline object at(const T& key)
378 LUABIND_PROXY_AT_BODY
379 #else
380 template<class T>
381 inline object at(const T& key);
382 #endif
385 template<class T>
386 inline object raw_at(const T& key)
388 lua_State* L = lua_state();
389 pushvalue();
390 detail::convert_to_lua(L, key);
391 lua_rawget(L, -2);
392 int ref = detail::ref(L);
393 lua_pop(L, 1);
394 return object(L, ref, true);
397 template<class T>
398 inline object at(const T& key)
400 lua_State* L = lua_state();
401 pushvalue();
402 detail::convert_to_lua(L, key);
403 lua_gettable(L, -2);
404 int ref = detail::ref(L);
405 lua_pop(L, 1);
406 return object(L, ref, true);
409 inline bool is_valid() const { return true; }
410 lua_State* lua_state() const;
411 void pushvalue() const;
412 void set() const;
414 // this is a safe substitute for an implicit converter to bool
415 typedef void (proxy_raw_object::*member_ptr)() const;
416 operator member_ptr() const
418 if (is_valid()) return &proxy_raw_object::dummy;
419 return 0;
423 private:
425 void dummy() const {}
427 proxy_raw_object(luabind::object* o, int key)
428 : m_obj(o)
429 , m_key_ref(key)
433 luabind::object* m_obj;
434 int m_key_ref;
439 class proxy_array_object
441 friend class luabind::object;
442 friend class luabind::detail::proxy_object;
443 friend class luabind::detail::proxy_raw_object;
444 // template<class T> friend T object_cast(const proxy_array_object& obj);
445 public:
447 template<class T>
448 proxy_array_object& operator=(const T& val)
450 //std::cout << "array proxy assigment\n";
451 lua_State* L = m_obj->m_state;
452 m_obj->pushvalue();
453 detail::convert_to_lua(L, val);
454 lua_rawseti(L, -2, m_key);
456 // pops the table
457 lua_pop(L, 1);
458 return *this;
461 proxy_array_object& operator=(const object& p);
462 proxy_array_object& operator=(const proxy_object& p);
463 proxy_array_object& operator=(const proxy_raw_object& p);
464 proxy_array_object& operator=(const proxy_array_object& p);
465 void swap(const proxy_array_object& rhs);
467 operator luabind::object();
469 int type() const
471 pushvalue();
472 detail::stack_pop p(lua_state(), 1);
473 return lua_type(lua_state(), -1);
476 #define LUABIND_PROXY_ARRAY_RAW_AT_BODY \
478 pushvalue(); \
479 detail::convert_to_lua(m_state, key); \
480 lua_rawget(m_state, -2); \
481 int ref = detail::ref(m_state); \
482 lua_pop(m_state, 1); \
483 return object(m_state, ref, true); \
486 #define LUABIND_PROXY_ARRAY_AT_BODY \
488 pushvalue(); \
489 detail::convert_to_lua(m_state, key); \
490 lua_gettable(m_state, -2); \
491 int ref = detail::ref(m_state); \
492 lua_pop(m_state, 1); \
493 return object(m_state, ref, true); \
496 #if defined(BOOST_MSVC) && (BOOST_MSVC <= 1300)
497 template<class T>
498 inline object at(const T& key)
499 LUABIND_PROXY_ARRAY_AT_BODY
500 #else
501 template<class T>
502 inline object at(const T& key);
503 #endif
506 #if defined(BOOST_MSVC) && (BOOST_MSVC <= 1300)
507 template<class T>
508 inline object raw_at(const T& key)
509 LUABIND_PROXY_ARRAY_RAW_AT_BODY
510 #else
511 template<class T>
512 inline object raw_at(const T& key);
513 #endif
515 template<class T>
516 inline object raw_at(const T& key)
518 pushvalue();
519 detail::convert_to_lua(m_state, key);
520 lua_rawget(m_state, -2);
521 int ref = detail::ref(m_state);
522 lua_pop(m_state, 1);
523 return object(m_state, ref, true);
526 template<class T>
527 inline object at(const T& key)
529 pushvalue();
530 detail::convert_to_lua(m_state, key);
531 lua_gettable(m_state, -2);
532 int ref = detail::ref(m_state);
533 lua_pop(m_state, 1);
534 return object(m_state, ref, true);
537 template<class T>
538 inline detail::proxy_object operator[](const T& key) const
540 detail::convert_to_lua(m_state, key);
541 int ref = detail::ref(m_state);
542 return detail::proxy_object(const_cast<object*>(this), ref);
545 inline bool is_valid() const { return true; }
546 lua_State* lua_state() const;
547 void pushvalue() const;
548 void set() const;
550 // this is a safe substitute for an implicit converter to bool
551 typedef void (proxy_array_object::*member_ptr)() const;
552 operator member_ptr() const
554 if (is_valid()) return &proxy_array_object::dummy;
555 return 0;
558 private:
560 void dummy() const {}
562 proxy_array_object(luabind::object* o, int key)
563 : m_obj(o)
564 , m_key(key)
567 luabind::object* m_obj;
568 int m_key;
571 template<class T>
572 struct primitive_converter;
574 } // detail
579 class object
582 #if !(defined (BOOST_MSVC) && (BOOST_MSVC <= 1200))
584 template<class T>
585 friend T object_cast(const object& obj);
586 template<class T>
587 friend struct detail::primitive_converter;
589 #endif
591 friend object get_globals(lua_State*);
592 friend object get_registry(lua_State*);
593 friend object newtable(lua_State*);
594 friend class detail::proxy_object;
595 friend class detail::proxy_array_object;
596 friend class detail::proxy_raw_object;
598 public:
600 class array_iterator
602 friend class object;
603 public:
605 typedef std::forward_iterator_tag iterator_category;
606 typedef luabind::object value_type;
607 typedef value_type& reference;
608 typedef value_type* pointer;
609 typedef void difference_type;
611 array_iterator()
612 : m_obj(0)
613 , m_key(LUA_NOREF)
617 array_iterator(const array_iterator& iter)
618 : m_obj(iter.m_obj)
619 , m_key(iter.m_key)
623 ~array_iterator() {}
625 array_iterator& operator=(const array_iterator& rhs)
627 //std::cout << "===\n";
628 m_obj = rhs.m_obj;
629 m_key = rhs.m_key;
630 return *this;
633 detail::proxy_array_object operator*()
635 return m_obj->make_array_proxy(m_key);
638 inline array_iterator& operator++()
640 m_key++;
642 // invalidate the iterator if we hit a nil element
643 lua_State* L = m_obj->lua_state();
644 m_obj->pushvalue();
645 lua_rawgeti(L, -1, m_key);
646 if (lua_isnil(L, -1)) m_key = LUA_NOREF;
647 lua_pop(L, 1);
649 return *this;
652 inline array_iterator operator++(int)
654 int old_key = m_key;
655 m_key++;
657 // invalidate the iterator if we hit a nil element
658 lua_State* L = m_obj->lua_state();
659 m_obj->pushvalue();
660 lua_rawgeti(L, -1, m_key);
661 if (lua_isnil(L, -1)) m_key = LUA_NOREF;
662 lua_pop(L, 1);
664 return array_iterator(m_obj, old_key);
667 bool operator!=(const array_iterator& rhs) const
669 return m_obj != rhs.m_obj || m_key != rhs.m_key;
672 private:
674 array_iterator(object* obj, int key)
675 : m_obj(obj)
676 , m_key(key)
680 object* m_obj;
681 int m_key;
689 class iterator
691 friend class object;
692 public:
694 typedef std::forward_iterator_tag iterator_category;
695 typedef luabind::object value_type;
696 typedef value_type& reference;
697 typedef value_type* pointer;
698 typedef void difference_type;
700 iterator()
701 : m_obj(0)
702 , m_key(LUA_NOREF)
706 iterator(const iterator& iter)
707 : m_obj(iter.m_obj)
708 , m_key(LUA_NOREF)
710 if (m_obj)
712 lua_State* L = m_obj->lua_state();
713 detail::getref(L, iter.m_key);
714 m_key = detail::ref(L);
718 ~iterator()
720 if (m_obj && m_key != LUA_NOREF) detail::unref(m_obj->lua_state(), m_key);
723 iterator& operator=(const iterator& rhs)
725 //std::cout << "===\n";
726 m_obj = rhs.m_obj;
727 if (m_obj)
729 lua_State* L = m_obj->lua_state();
730 detail::getref(L, rhs.m_key);
731 m_key = detail::ref(L);
733 else
735 m_key = LUA_NOREF;
737 return *this;
740 detail::proxy_object operator*()
742 return m_obj->make_proxy(m_key);
745 iterator& operator++()
747 lua_State* L = m_obj->lua_state();
748 m_obj->pushvalue();
749 detail::getref(L, m_key);
751 if (lua_next(L, -2) != 0)
753 lua_pop(L, 1);
754 lua_rawseti(L, LUA_REGISTRYINDEX, m_key);
755 lua_pop(L, 1);
757 else
759 lua_pop(L, 1);
760 detail::unref(L, m_key);
761 m_obj = 0;
762 m_key = LUA_NOREF;
765 return *this;
768 bool operator!=(const iterator& rhs) const
770 return m_obj != rhs.m_obj || m_key != rhs.m_key;
773 private:
775 iterator(object* obj, int key)
776 : m_obj(obj)
777 , m_key(key)
781 object* m_obj;
782 int m_key;
788 class raw_iterator
790 friend class object;
791 public:
793 typedef std::forward_iterator_tag iterator_category;
794 typedef luabind::object value_type;
795 typedef value_type& reference;
796 typedef value_type* pointer;
797 typedef void difference_type;
799 raw_iterator()
800 : m_obj(0)
801 , m_key(LUA_NOREF)
805 raw_iterator(const raw_iterator& iter)
806 : m_obj(iter.m_obj)
807 , m_key(LUA_NOREF)
809 if (m_obj)
811 lua_State* L = m_obj->lua_state();
812 detail::getref(L, iter.m_key);
813 m_key = detail::ref(L);
817 ~raw_iterator()
819 if (m_obj && m_key != LUA_NOREF) detail::unref(m_obj->lua_state(), m_key);
822 raw_iterator& operator=(const raw_iterator& rhs)
824 //std::cout << "===\n";
825 m_obj = rhs.m_obj;
826 if (m_obj)
828 lua_State* L = m_obj->lua_state();
829 detail::getref(L, rhs.m_key);
830 m_key = detail::ref(L);
832 else
834 m_key = LUA_NOREF;
836 return *this;
839 detail::proxy_raw_object operator*()
841 return m_obj->make_raw_proxy(m_key);
844 raw_iterator& operator++()
846 lua_State* L = m_obj->lua_state();
847 m_obj->pushvalue();
848 detail::getref(L, m_key);
850 if (lua_next(L, -2) != 0)
852 lua_pop(L, 1);
853 lua_rawseti(L, LUA_REGISTRYINDEX, m_key);
854 lua_pop(L, 1);
856 else
858 lua_pop(L, 1);
859 detail::unref(L, m_key);
860 m_obj = 0;
861 m_key = LUA_NOREF;
864 return *this;
867 bool operator!=(const raw_iterator& rhs) const
869 return m_obj != rhs.m_obj || m_key != rhs.m_key;
872 private:
874 raw_iterator(object* obj, int key)
875 : m_obj(obj)
876 , m_key(key)
880 object* m_obj;
881 int m_key;
889 object()
890 : m_state(0)
891 , m_ref(LUA_NOREF)
895 object(lua_State* L)
896 : m_state(L)
897 , m_ref(LUA_NOREF)
901 template<class T>
902 object(lua_State* L, const T& val)
903 : m_state(L)
904 , m_ref(LUA_NOREF)
906 *this = val;
909 object(const object& o)
910 : m_state(o.m_state)
911 , m_ref(LUA_NOREF)
913 lua_getref(m_state, o.m_ref);
914 m_ref = detail::ref(m_state);
917 inline ~object()
919 // If you crash in the detail::unref() call you have probably
920 // closed the lua_State before destructing all object instances.
921 if (m_ref != LUA_NOREF) detail::unref(m_state, m_ref);
924 inline bool is_valid() const { return m_ref != LUA_NOREF; }
926 // this is a safe substitute for an implicit converter to bool
927 typedef void (object::*member_ptr)() const;
928 operator member_ptr() const
930 if (is_valid()) return &object::dummy;
931 return 0;
934 int type() const
936 pushvalue();
937 detail::stack_pop p(lua_state(), 1);
938 return lua_type(lua_state(), -1);
941 inline iterator begin() const
943 lua_getref(m_state, m_ref);
944 lua_pushnil(m_state);
945 lua_next(m_state, -2);
946 lua_pop(m_state, 1);
947 iterator i(const_cast<object*>(this), detail::ref(m_state));
948 lua_pop(m_state, 1);
949 return i;
952 inline iterator end() const
954 return iterator(0, LUA_NOREF);
957 inline array_iterator abegin() const
959 // TODO: This should start counting at 1, right?
960 return array_iterator(const_cast<object*>(this), 1);
963 inline array_iterator aend() const
965 return array_iterator(const_cast<object*>(this), LUA_NOREF);
968 raw_iterator raw_begin() const
970 lua_getref(m_state, m_ref);
971 lua_pushnil(m_state);
972 lua_next(m_state, -2);
973 lua_pop(m_state, 1);
974 raw_iterator i(const_cast<object*>(this), detail::ref(m_state));
975 lua_pop(m_state, 1);
976 return i;
979 raw_iterator raw_end() const
981 return raw_iterator(0, LUA_NOREF);
984 inline void set() const
986 // you are trying to access an invalid object
987 assert((m_state != 0) && "you are trying to access an invalid (uninitialized) object");
989 allocate_slot();
990 lua_rawseti(m_state, LUA_REGISTRYINDEX, m_ref);
992 inline lua_State* lua_state() const { return m_state; }
993 inline void pushvalue() const
995 // you are trying to dereference an invalid object
996 assert((m_ref != LUA_NOREF) && "you are trying to access an invalid (uninitialized) object");
997 assert((m_state != 0) && "internal error, please report");
999 lua_getref(m_state, m_ref);
1002 void swap(object& rhs);
1004 template<class T>
1005 inline object raw_at(const T& key)
1007 lua_State* L = lua_state();
1008 pushvalue();
1009 detail::convert_to_lua(L, key);
1010 lua_rawget(L, -2);
1011 int ref = detail::ref(L);
1012 lua_pop(L, 1);
1013 return object(L, ref, true);
1016 template<class T>
1017 inline object at(const T& key)
1019 lua_State* L = lua_state();
1020 pushvalue();
1021 detail::convert_to_lua(L, key);
1022 lua_gettable(L, -2);
1023 int ref = detail::ref(L);
1024 lua_pop(L, 1);
1025 return object(L, ref, true);
1028 template<class T>
1029 inline detail::proxy_object operator[](const T& key) const
1031 detail::convert_to_lua(m_state, key);
1032 int ref = detail::ref(m_state);
1033 return detail::proxy_object(const_cast<object*>(this), ref);
1038 // *****************************
1039 // OPERATOR =
1042 object& operator=(const object& o) const
1044 m_state = o.lua_state();
1045 allocate_slot();
1046 o.pushvalue();
1047 //TODO: move lua_rawseti into a function set_ref() or something
1048 lua_rawseti(m_state, LUA_REGISTRYINDEX, m_ref);
1049 return const_cast<luabind::object&>(*this);
1052 object& operator=(const detail::proxy_object& o) const
1054 m_state = o.lua_state();
1055 allocate_slot();
1056 o.pushvalue();
1057 lua_rawseti(m_state, LUA_REGISTRYINDEX, m_ref);
1058 return const_cast<luabind::object&>(*this);
1061 object& operator=(const detail::proxy_raw_object& o) const
1063 m_state = o.lua_state();
1064 allocate_slot();
1065 o.pushvalue();
1066 lua_rawseti(m_state, LUA_REGISTRYINDEX, m_ref);
1067 return const_cast<luabind::object&>(*this);
1070 object& operator=(const detail::proxy_array_object& o) const
1072 m_state = o.lua_state();
1073 allocate_slot();
1074 o.pushvalue();
1075 lua_rawseti(m_state, LUA_REGISTRYINDEX, m_ref);
1076 return const_cast<luabind::object&>(*this);
1079 template<class T>
1080 object& operator=(const T& val) const
1082 assert((m_state != 0) && "you cannot assign a non-lua value to an uninitialized object");
1083 // you cannot assign a non-lua value to an uninitialized object
1085 allocate_slot();
1086 detail::convert_to_lua(m_state, val);
1087 lua_rawseti(m_state, LUA_REGISTRYINDEX, m_ref);
1088 return const_cast<luabind::object&>(*this);
1092 // *****************************
1093 // OPERATOR ==
1096 bool operator==(const object& rhs) const
1098 if (m_ref == LUA_NOREF || rhs.m_ref == LUA_NOREF) return false;
1099 lua_getref(m_state, m_ref);
1100 rhs.pushvalue();
1101 bool result = lua_equal(m_state, -1, -2) != 0;
1102 lua_pop(m_state, 2);
1103 return result;
1106 bool operator==(const detail::proxy_object& rhs) const
1108 if (m_ref == LUA_NOREF) return false;
1109 lua_getref(m_state, m_ref);
1110 rhs.pushvalue();
1111 bool result = lua_equal(m_state, -1, -2) != 0;
1112 lua_pop(m_state, 2);
1113 return result;
1116 bool operator==(const detail::proxy_raw_object& rhs) const
1118 if (m_ref == LUA_NOREF) return false;
1119 lua_getref(m_state, m_ref);
1120 rhs.pushvalue();
1121 bool result = lua_equal(m_state, -1, -2) != 0;
1122 lua_pop(m_state, 2);
1123 return result;
1126 bool operator==(const detail::proxy_array_object& rhs) const
1128 if (m_ref == LUA_NOREF) return false;
1129 lua_getref(m_state, m_ref);
1130 rhs.pushvalue();
1131 bool result = lua_equal(m_state, -1, -2) != 0;
1132 lua_pop(m_state, 2);
1133 return result;
1136 template<class T>
1137 bool operator==(const T& rhs) const
1139 if (m_ref == LUA_NOREF) return false;
1140 lua_getref(m_state, m_ref);
1141 detail::convert_to_lua(m_state, rhs);
1143 bool result = lua_equal(m_state, -1, -2);
1145 lua_pop(m_state, 2);
1146 return result;
1151 // *****************************
1152 // OPERATOR()
1154 #define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, <luabind/object.hpp>, 1))
1155 #include BOOST_PP_ITERATE()
1159 inline detail::proxy_object make_proxy(int key)
1161 return detail::proxy_object(this, key);
1164 inline detail::proxy_raw_object make_raw_proxy(int key)
1166 return detail::proxy_raw_object(this, key);
1169 inline detail::proxy_array_object make_array_proxy(int key)
1171 return detail::proxy_array_object(this, key);
1174 // TODO: it's not possible to make object friend with wrapped_constructor_helper::apply (since
1175 // it's an inner class), that's why this interface is public
1176 // private:
1178 struct stack_index {};
1179 struct reference {};
1182 object(lua_State* L, int index, stack_index)
1183 : m_state(L)
1185 lua_pushvalue(L, index);
1186 m_ref = detail::ref(L);
1189 object(lua_State* L, int ref, bool/*, reference*/)
1190 : m_state(L)
1191 , m_ref(ref)
1195 private:
1197 void dummy() const {}
1199 void allocate_slot() const
1201 if (m_ref == LUA_NOREF)
1203 lua_pushboolean(m_state, 0);
1204 m_ref = detail::ref(m_state);
1208 mutable lua_State* m_state;
1209 mutable int m_ref;
1213 // *************************************
1214 // OBJECT
1216 inline void object::swap(object& rhs)
1218 // you cannot swap objects from different lua states
1219 assert((lua_state() == rhs.lua_state()) && "you cannot swap objects from different lua states");
1220 std::swap(m_ref, rhs.m_ref);
1223 namespace detail
1226 // *************************************
1227 // PROXY CALLER
1229 #if !defined(BOOST_MSVC) || (defined(BOOST_MSVC) && (BOOST_MSVC > 1300))
1230 template<class Tuple>
1231 template<class Policies>
1232 luabind::object proxy_caller<Tuple>::operator[](const Policies& p)
1234 m_called = true;
1235 lua_State* L = m_obj->lua_state();
1236 m_obj->pushvalue();
1237 detail::push_args_from_tuple<1>::apply(L, m_args, p);
1238 if (lua_pcall(L, boost::tuples::length<Tuple>::value, 1, 0))
1240 #ifndef LUABIND_NO_EXCEPTIONS
1241 throw error(L);
1242 #else
1243 error_callback_fun e = detail::error_callback::get().err;
1244 if (e) e(L);
1246 assert(0 && "the lua function threw an error and exceptions are disabled."
1247 "if you want to handle this error use luabind::set_error_callback()");
1248 std::terminate();
1249 #endif
1251 int ref = detail::ref(L);
1252 return luabind::object(m_obj->lua_state(), ref, true/*luabind::object::reference()*/);
1254 #endif
1255 // *************************************
1256 // PROXY OBJECT
1258 #if !defined(BOOST_MSVC) || (defined(BOOST_MSVC) && (BOOST_MSVC > 1300))
1259 template<class T>
1260 inline object proxy_object::raw_at(const T& key)
1261 LUABIND_PROXY_RAW_AT_BODY
1263 template<class T>
1264 inline object proxy_object::at(const T& key)
1265 LUABIND_PROXY_AT_BODY
1266 #endif
1268 inline proxy_object& proxy_object::operator=(const object& p)
1270 assert((lua_state() == p.lua_state()) && "you cannot assign a value from a different lua state");
1272 lua_State* L = lua_state();
1274 m_obj->pushvalue();
1275 detail::getref(L, m_key_ref);
1277 // retrive the rhs value
1278 p.pushvalue();
1280 lua_settable(L, -3);
1281 lua_pop(L, 1);
1282 return *this;
1285 inline proxy_object& proxy_object::operator=(const proxy_object& p)
1287 // if you hit this assert you are trying to transfer values from one lua state to another
1288 // without first going through C++
1289 assert((lua_state() == p.lua_state()) && "you cannot assign a value from a different lua state");
1291 lua_State* L = lua_state();
1293 //std::cout << "proxy-proxy assigment\n";
1294 m_obj->pushvalue();
1295 detail::getref(L, m_key_ref);
1297 // retrive the rhs value
1298 p.pushvalue();
1300 lua_settable(L, -3);
1301 lua_pop(L, 1);
1302 return *this;
1305 inline proxy_object& proxy_object::operator=(const proxy_raw_object& p)
1307 // if you hit this assert you are trying to transfer values from one lua state to another
1308 // without first going through C++
1309 assert((lua_state() == p.lua_state()) && "you cannot assign a value from a different lua state");
1311 lua_State* L = lua_state();
1313 //std::cout << "proxy-proxy assigment\n";
1314 m_obj->pushvalue();
1315 detail::getref(L, m_key_ref);
1317 // retrive the rhs value
1318 p.pushvalue();
1320 lua_settable(L, -3);
1321 lua_pop(L, 1);
1322 return *this;
1325 inline proxy_object& proxy_object::operator=(const proxy_array_object& p)
1327 // if you hit this assert you are trying to transfer values from one lua state to another
1328 // without first going through C++
1329 assert((lua_state() == p.lua_state()) && "you cannot assign a value from a different lua state");
1331 lua_State* L = lua_state();
1333 //std::cout << "proxy-proxy assigment\n";
1334 m_obj->pushvalue();
1335 detail::getref(L, m_key_ref);
1337 // retrive the rhs value
1338 p.pushvalue();
1340 lua_settable(L, -3);
1341 lua_pop(L, 1);
1342 return *this;
1345 inline void proxy_object::pushvalue() const
1347 assert((m_key_ref != LUA_NOREF) && "you cannot call pushvalue() on an uninitialized object");
1349 lua_State* L = m_obj->lua_state();
1350 m_obj->pushvalue();
1351 detail::getref(L, m_key_ref);
1352 lua_gettable(L, -2);
1353 // remove the table and leave the value on top of the stack
1354 lua_remove(L, -2);
1357 inline lua_State* proxy_object::lua_state() const
1359 return m_obj->lua_state();
1362 inline void proxy_object::set() const
1364 lua_State* L = lua_state();
1365 m_obj->pushvalue();
1366 detail::getref(L, m_key_ref);
1367 lua_pushvalue(L, -3);
1368 lua_settable(L, -3);
1369 // pop table and value
1370 lua_pop(L, 2);
1373 inline proxy_object::operator luabind::object()
1375 lua_State* L = m_obj->lua_state();
1376 pushvalue();
1377 int ref = detail::ref(L);
1378 return luabind::object(L, ref, true/*luabind::object::reference()*/);
1382 // *************************************
1383 // PROXY ARRAY OBJECT
1385 #if !defined(BOOST_MSVC) || (defined(BOOST_MSVC) && (BOOST_MSVC > 1300))
1386 template<class T>
1387 inline object proxy_array_object::raw_at(const T& key)
1388 LUABIND_PROXY_ARRAY_RAW_AT_BODY
1390 template<class T>
1391 inline object proxy_array_object::at(const T& key)
1392 LUABIND_PROXY_ARRAY_AT_BODY
1393 #endif
1395 #undef LUABIND_PROXY_ARRAY_AT_BODY
1396 #undef LUABIND_PROXY_ARRAY_RAW_AT_BODY
1398 inline proxy_array_object& proxy_array_object::operator=(const object& p)
1400 // if you hit this assert you are trying to transfer values
1401 // from one lua state to another without first going through C++
1402 assert((lua_state() == p.lua_state()) && "you cannot assign a value from a different lua state");
1403 lua_State* L = lua_state();
1404 m_obj->pushvalue();
1405 // retrieve the rhs value
1406 p.pushvalue();
1408 lua_rawseti(L, -2, m_key);
1409 lua_pop(L, 1);
1410 return *this;
1413 inline proxy_array_object& proxy_array_object::operator=(const proxy_object& p)
1415 // if you hit this assert you are trying to transfer values from one lua state to another
1416 // without first going through C++
1417 assert((lua_state() == p.lua_state()) && "you cannot assign a value from a different lua state");
1419 lua_State* L = lua_state();
1421 //std::cout << "proxy-proxy assigment\n";
1422 m_obj->pushvalue();
1424 // retrieve the rhs value
1425 p.pushvalue();
1427 lua_rawseti(L, -2, m_key);
1428 lua_pop(L, 1);
1429 return *this;
1432 inline proxy_array_object& proxy_array_object::operator=(const proxy_raw_object& p)
1434 // if you hit this assert you are trying to transfer values from one lua state to another
1435 // without first going through C++
1436 assert((lua_state() == p.lua_state()) && "you cannot assign a value from a different lua state");
1438 lua_State* L = lua_state();
1440 m_obj->pushvalue();
1441 p.pushvalue();
1443 lua_rawseti(L, -2, m_key);
1444 lua_pop(L, 1);
1445 return *this;
1448 inline proxy_array_object& proxy_array_object::operator=(const proxy_array_object& p)
1450 // if you hit this assert you are trying to transfer values from one lua state to another
1451 // without first going through C++
1452 assert((lua_state() == p.lua_state()) && "you cannot assign a value from a different lua state");
1454 lua_State* L = lua_state();
1456 m_obj->pushvalue();
1457 p.pushvalue();
1459 lua_rawseti(L, -2, m_key);
1460 lua_pop(L, 1);
1461 return *this;
1464 inline lua_State* proxy_array_object::lua_state() const
1466 return m_obj->lua_state();
1469 inline void proxy_array_object::pushvalue() const
1471 // you are trying to dereference an invalid object
1472 assert((m_key != LUA_NOREF) && "you cannot call pushvalue() on an uninitialized object");
1474 lua_State* L = m_obj->lua_state();
1475 m_obj->pushvalue();
1476 lua_rawgeti(L, -1, m_key);
1477 lua_remove(L, -2);
1480 inline void proxy_array_object::set() const
1482 lua_State* L = lua_state();
1483 m_obj->pushvalue();
1484 lua_pushvalue(L, -2);
1485 lua_rawseti(L, -2, m_key);
1486 // pop table and value
1487 lua_pop(L, 2);
1490 inline proxy_array_object::operator luabind::object()
1492 lua_State* L = m_obj->lua_state();
1493 pushvalue();
1494 int ref = detail::ref(L);
1495 return luabind::object(L, ref, true/*luabind::object::reference()*/);
1499 // *************************************
1500 // PROXY RAW OBJECT
1502 #if !defined(BOOST_MSVC) || (defined(BOOST_MSVC) && (BOOST_MSVC > 1300))
1503 template<class T>
1504 inline object proxy_raw_object::raw_at(const T& key)
1505 LUABIND_PROXY_RAW_AT_BODY
1507 template<class T>
1508 inline object proxy_raw_object::at(const T& key)
1509 LUABIND_PROXY_AT_BODY
1510 #endif
1512 #undef LUABIND_PROXY_RAW_AT_BODY
1513 #undef LUABIND_PROXY_AT_BODY
1515 inline proxy_raw_object& proxy_raw_object::operator=(const object& p)
1517 // if you hit this assert you are trying to transfer values from one lua state to another
1518 // without first going through C++
1519 assert((lua_state() == p.lua_state()) && "you cannot assign a value from a different lua state");
1520 lua_State* L = lua_state();
1522 m_obj->pushvalue();
1523 detail::getref(L, m_key_ref);
1525 // retrive the rhs value
1526 p.pushvalue();
1528 lua_rawset(L, -3);
1529 lua_pop(L, 1);
1530 return *this;
1534 inline proxy_raw_object& proxy_raw_object::operator=(const proxy_object& p)
1536 // if you hit this assert you are trying to transfer values from one lua state to another
1537 // without first going through C++
1538 assert((lua_state() == p.lua_state()) && "you cannot assign a value from a different lua state");
1540 lua_State* L = lua_state();
1542 //std::cout << "proxy-proxy assigment\n";
1543 m_obj->pushvalue();
1544 detail::getref(L, m_key_ref);
1546 // retrive the rhs value
1547 p.pushvalue();
1549 lua_rawset(L, -3);
1550 lua_pop(L, 1);
1551 return *this;
1554 inline proxy_raw_object& proxy_raw_object::operator=(const proxy_raw_object& p)
1556 // if you hit this assert you are trying to transfer values from one lua state to another
1557 // without first going through C++
1558 assert((lua_state() == p.lua_state()) && "you cannot assign a value from a different lua state");
1560 lua_State* L = lua_state();
1562 //std::cout << "proxy-proxy assigment\n";
1563 m_obj->pushvalue();
1564 detail::getref(L, m_key_ref);
1566 // retrive the rhs value
1567 p.pushvalue();
1569 lua_rawset(L, -3);
1570 lua_pop(L, 1);
1571 return *this;
1574 inline proxy_raw_object& proxy_raw_object::operator=(const proxy_array_object& p)
1576 // if you hit this assert you are trying to transfer values from one lua state to another
1577 // without first going through C++
1578 assert((lua_state() == p.lua_state()) && "you cannot assign a value from a different lua state");
1580 lua_State* L = lua_state();
1582 //std::cout << "proxy-proxy assigment\n";
1583 m_obj->pushvalue();
1584 detail::getref(L, m_key_ref);
1586 // retrive the rhs value
1587 p.m_obj->pushvalue();
1588 lua_rawgeti(L, -1, p.m_key);
1590 lua_rawset(L, -3);
1591 lua_pop(L, 1);
1592 return *this;
1595 inline void proxy_raw_object::pushvalue() const
1597 assert((m_key_ref != LUA_NOREF) && "you cannot call pushvalue() on an uninitiallized object");
1599 lua_State* L = lua_state();
1600 m_obj->pushvalue();
1601 detail::getref(L, m_key_ref);
1602 lua_rawget(L, -2);
1603 // remove the table and leave the value on top of the stack
1604 lua_remove(L, -2);
1607 inline void proxy_raw_object::set() const
1609 lua_State* L = lua_state();
1610 m_obj->pushvalue();
1611 detail::getref(L, m_key_ref);
1612 lua_pushvalue(L, -3);
1613 lua_rawset(L, -3);
1614 // pop table and value
1615 lua_pop(L, 2);
1618 inline lua_State* proxy_raw_object::lua_state() const
1620 return m_obj->lua_state();
1623 inline proxy_raw_object::operator luabind::object()
1625 lua_State* L = lua_state();
1626 pushvalue();
1627 int ref = detail::ref(L);
1628 return luabind::object(L, ref, true/*luabind::object::reference()*/);
1632 // *************************************
1633 // PROXY CALLER
1636 template<class Tuple>
1637 proxy_caller<Tuple>::~proxy_caller()
1639 if (m_called) return;
1641 m_called = true;
1642 lua_State* L = m_obj->lua_state();
1643 m_obj->pushvalue();
1645 push_args_from_tuple<1>::apply(L, m_args);
1646 if (lua_pcall(L, boost::tuples::length<Tuple>::value, 0, 0))
1648 #ifndef LUABIND_NO_EXCEPTIONS
1649 throw luabind::error(L);
1650 #else
1651 error_callback_fun e = detail::error_callback::get().err;
1652 if (e) e(L);
1654 assert(0 && "the lua function threw an error and exceptions are disabled."
1655 "if you want to handle this error use luabind::set_error_callback()");
1656 std::terminate();
1657 #endif
1661 template<class Tuple>
1662 proxy_caller<Tuple>::operator luabind::object()
1664 m_called = true;
1665 lua_State* L = m_obj->lua_state();
1666 m_obj->pushvalue();
1668 push_args_from_tuple<1>::apply(L, m_args);
1669 if (lua_pcall(L, boost::tuples::length<Tuple>::value, 1, 0))
1671 #ifndef LUABIND_NO_EXCEPTIONS
1672 throw luabind::error(L);
1673 #else
1674 error_callback_fun e = detail::error_callback::get().err;
1675 if (e) e(L);
1677 assert(0 && "the lua function threw an error and exceptions are disabled."
1678 "if you want to handle this error use luabind::set_error_callback()");
1679 std::terminate();
1680 #endif
1682 int ref = detail::ref(L);
1683 return luabind::object(m_obj->lua_state(), ref, true/*luabind::object::reference()*/);
1690 namespace std
1693 #define LUABIND_DEFINE_SWAP(t1,t2)\
1694 inline void swap(t1 lhs, t2 rhs)\
1696 assert((lhs.lua_state() == rhs.lua_state()) && "you cannot swap objects from different lua states");\
1697 rhs.pushvalue();\
1698 lhs.pushvalue();\
1699 rhs.set();\
1700 lhs.set();\
1703 inline void swap(luabind::object& lhs, luabind::object& rhs)
1705 lhs.swap(rhs);
1708 // object against all other
1709 LUABIND_DEFINE_SWAP(luabind::object&, const luabind::detail::proxy_object&)
1710 LUABIND_DEFINE_SWAP(luabind::object&, const luabind::detail::proxy_raw_object&)
1711 LUABIND_DEFINE_SWAP(luabind::object&, const luabind::detail::proxy_array_object&)
1712 LUABIND_DEFINE_SWAP(const luabind::detail::proxy_object&, luabind::object&)
1713 LUABIND_DEFINE_SWAP(const luabind::detail::proxy_raw_object&, luabind::object&)
1714 LUABIND_DEFINE_SWAP(const luabind::detail::proxy_array_object&, luabind::object&)
1716 // proxy_object against all other
1717 LUABIND_DEFINE_SWAP(const luabind::detail::proxy_object&, const luabind::detail::proxy_object&)
1718 LUABIND_DEFINE_SWAP(const luabind::detail::proxy_object&, const luabind::detail::proxy_raw_object&)
1719 LUABIND_DEFINE_SWAP(const luabind::detail::proxy_object&, const luabind::detail::proxy_array_object&)
1720 LUABIND_DEFINE_SWAP(const luabind::detail::proxy_raw_object&, const luabind::detail::proxy_object&)
1721 LUABIND_DEFINE_SWAP(const luabind::detail::proxy_array_object&, const luabind::detail::proxy_object&)
1723 // proxy_raw_object against all other
1724 LUABIND_DEFINE_SWAP(const luabind::detail::proxy_raw_object&, const luabind::detail::proxy_raw_object&)
1725 LUABIND_DEFINE_SWAP(const luabind::detail::proxy_raw_object&, const luabind::detail::proxy_array_object&)
1726 LUABIND_DEFINE_SWAP(const luabind::detail::proxy_array_object&, const luabind::detail::proxy_raw_object&)
1728 // proxy_array_object against all other
1729 LUABIND_DEFINE_SWAP(const luabind::detail::proxy_array_object&, const luabind::detail::proxy_array_object&)
1731 #undef LUABIND_DEFINE_SWAP
1735 #endif // LUABIND_OBJECT_HPP_INCLUDED
1737 #elif BOOST_PP_ITERATION_FLAGS() == 1
1739 #define LUABIND_TUPLE_PARAMS(z, n, data) const A##n *
1740 #define LUABIND_OPERATOR_PARAMS(z, n, data) const A##n & a##n
1742 #if BOOST_PP_ITERATION() > 0
1743 template<BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A)>
1744 #endif
1745 detail::proxy_caller<boost::tuples::tuple<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS, _)> >
1746 operator()(BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_OPERATOR_PARAMS, _)) const
1748 typedef boost::tuples::tuple<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS, _)> tuple_t;
1749 #if BOOST_PP_ITERATION() == 0
1750 tuple_t args;
1751 #else
1752 tuple_t args(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), &a));
1753 #endif
1754 return detail::proxy_caller<tuple_t>(const_cast<luabind::object*>(this), args);
1757 #undef LUABIND_OPERATOR_PARAMS
1758 #undef LUABIND_TUPLE_PARAMS
1760 #endif