1 //------------------------------------------------------------------------------
3 https://github.com/vinniefalco/LuaBridge
5 Copyright 2016, Robin Gareus <robin@gareus.org>
6 Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
8 License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
10 Permission is hereby granted, free of charge, to any person obtaining a copy
11 of this software and associated documentation files (the "Software"), to deal
12 in the Software without restriction, including without limitation the rights
13 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 copies of the Software, and to permit persons to whom the Software is
15 furnished to do so, subject to the following conditions:
17 The above copyright notice and this permission notice shall be included in all
18 copies or substantial portions of the Software.
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 //==============================================================================
30 // We use a structure so we can define everything in the header.
34 //----------------------------------------------------------------------------
36 __index metamethod for a namespace or class static members.
39 Retrieving functions and class static methods, stored in the metatable.
40 Reading global and class static data, stored in the __propget table.
41 Reading global and class properties, stored in the __propget table.
43 static int indexMetaMethod (lua_State* L)
46 lua_getmetatable (L, 1); // push metatable of arg1
49 lua_pushvalue (L, 2); // push key arg2
50 lua_rawget (L, -2); // lookup key in metatable
51 if (lua_isnil (L, -1)) // not found
53 lua_pop (L, 1); // discard nil
54 rawgetfield (L, -1, "__propget"); // lookup __propget in metatable
55 lua_pushvalue (L, 2); // push key arg2
56 lua_rawget (L, -2); // lookup key in __propget
57 lua_remove (L, -2); // discard __propget
58 if (lua_iscfunction (L, -1))
60 lua_remove (L, -2); // discard metatable
61 lua_pushvalue (L, 1); // push arg1
62 lua_call (L, 1, 1); // call cfunction
68 assert (lua_isnil (L, -1));
69 lua_pop (L, 1); // discard nil and fall through
74 assert (lua_istable (L, -1) || lua_iscfunction (L, -1));
80 rawgetfield (L, -1, "__parent");
81 if (lua_istable (L, -1))
83 // Remove metatable and repeat the search in __parent.
88 // Discard metatable and return nil.
89 assert (lua_isnil (L, -1));
99 //----------------------------------------------------------------------------
101 __newindex metamethod for a namespace or class static members.
103 The __propset table stores proxy functions for assignment to:
104 Global and class static data.
105 Global and class properties.
107 static int newindexMetaMethod (lua_State* L)
110 lua_getmetatable (L, 1); // push metatable of arg1
113 rawgetfield (L, -1, "__propset"); // lookup __propset in metatable
114 assert (lua_istable (L, -1));
115 lua_pushvalue (L, 2); // push key arg2
116 lua_rawget (L, -2); // lookup key in __propset
117 lua_remove (L, -2); // discard __propset
118 if (lua_iscfunction (L, -1)) // ensure value is a cfunction
120 lua_remove (L, -2); // discard metatable
121 lua_pushvalue (L, 3); // push new value arg3
122 lua_call (L, 1, 0); // call cfunction
128 assert (lua_isnil (L, -1));
132 rawgetfield (L, -1, "__parent");
133 if (lua_istable (L, -1))
135 // Remove metatable and repeat the search in __parent.
140 assert (lua_isnil (L, -1));
142 result = luaL_error (L,"no writable variable '%s'", lua_tostring (L, 2));
149 //----------------------------------------------------------------------------
151 lua_CFunction to report an error writing to a read-only value.
153 The name of the variable is in the first upvalue.
155 static int readOnlyError (lua_State* L)
159 s = s + "'" + lua_tostring (L, lua_upvalueindex (1)) + "' is read-only";
161 return luaL_error (L, s.c_str ());
164 //----------------------------------------------------------------------------
166 lua_CFunction to get a variable.
168 This is used for global variables or class static data members.
170 The pointer to the data is in the first upvalue.
173 static int getVariable (lua_State* L)
175 assert (lua_islightuserdata (L, lua_upvalueindex (1)));
176 T const* ptr = static_cast <T const*> (lua_touserdata (L, lua_upvalueindex (1)));
178 Stack <T>::push (L, *ptr);
182 //----------------------------------------------------------------------------
184 lua_CFunction to set a variable.
186 This is used for global variables or class static data members.
188 The pointer to the data is in the first upvalue.
191 static int setVariable (lua_State* L)
193 assert (lua_islightuserdata (L, lua_upvalueindex (1)));
194 T* ptr = static_cast <T*> (lua_touserdata (L, lua_upvalueindex (1)));
196 *ptr = Stack <T>::get (L, 1);
200 //----------------------------------------------------------------------------
202 lua_CFunction to call a function with a return value.
204 This is used for global functions, global properties, class static methods,
205 and class static properties.
207 The function pointer is in the first upvalue.
209 template <class FnPtr,
210 class ReturnType = typename FuncTraits <FnPtr>::ReturnType>
213 typedef typename FuncTraits <FnPtr>::Params Params;
214 static int f (lua_State* L)
216 assert (isfulluserdata (L, lua_upvalueindex (1)));
217 FnPtr const& fnptr = *static_cast <FnPtr const*> (lua_touserdata (L, lua_upvalueindex (1)));
219 ArgList <Params> args (L);
220 Stack <typename FuncTraits <FnPtr>::ReturnType>::push (L, FuncTraits <FnPtr>::call (fnptr, args));
225 //----------------------------------------------------------------------------
227 lua_CFunction to call a function with no return value.
229 This is used for global functions, global properties, class static methods,
230 and class static properties.
232 The function pointer is in the first upvalue.
234 template <class FnPtr>
235 struct Call <FnPtr, void>
237 typedef typename FuncTraits <FnPtr>::Params Params;
238 static int f (lua_State* L)
240 assert (isfulluserdata (L, lua_upvalueindex (1)));
241 FnPtr const& fnptr = *static_cast <FnPtr const*> (lua_touserdata (L, lua_upvalueindex (1)));
243 ArgList <Params> args (L);
244 FuncTraits <FnPtr>::call (fnptr, args);
249 //----------------------------------------------------------------------------
251 lua_CFunction to call a function with references as arguments.
253 template <class FnPtr,
254 class ReturnType = typename FuncTraits <FnPtr>::ReturnType>
257 typedef typename FuncTraits <FnPtr>::Params Params;
258 static int f (lua_State* L)
260 assert (isfulluserdata (L, lua_upvalueindex (1)));
261 FnPtr const& fnptr = *static_cast <FnPtr const*> (lua_touserdata (L, lua_upvalueindex (1)));
263 ArgList <Params, 1> args (L);
264 Stack <typename FuncTraits <FnPtr>::ReturnType>::push (L, FuncTraits <FnPtr>::call (fnptr, args));
265 LuaRef v (newTable (L));
266 FuncArgs <Params, 0>::refs (v, args);
272 template <class FnPtr>
273 struct CallRef <FnPtr, void>
275 typedef typename FuncTraits <FnPtr>::Params Params;
276 static int f (lua_State* L)
278 assert (isfulluserdata (L, lua_upvalueindex (1)));
279 FnPtr const& fnptr = *static_cast <FnPtr const*> (lua_touserdata (L, lua_upvalueindex (1)));
281 ArgList <Params, 1> args (L);
282 FuncTraits <FnPtr>::call (fnptr, args);
283 LuaRef v (newTable (L));
284 FuncArgs <Params, 0>::refs (v, args);
291 //----------------------------------------------------------------------------
293 lua_CFunction to call a class member function with a return value.
295 The member function pointer is in the first upvalue.
296 The class userdata object is at the top of the Lua stack.
298 template <class MemFnPtr,
299 class ReturnType = typename FuncTraits <MemFnPtr>::ReturnType>
302 typedef typename FuncTraits <MemFnPtr>::ClassType T;
303 typedef typename FuncTraits <MemFnPtr>::Params Params;
305 static int f (lua_State* L)
307 assert (isfulluserdata (L, lua_upvalueindex (1)));
308 T* const t = Userdata::get <T> (L, 1, false);
309 MemFnPtr const& fnptr = *static_cast <MemFnPtr const*> (lua_touserdata (L, lua_upvalueindex (1)));
311 ArgList <Params, 2> args (L);
312 Stack <ReturnType>::push (L, FuncTraits <MemFnPtr>::call (t, fnptr, args));
317 template <class MemFnPtr,
318 class ReturnType = typename FuncTraits <MemFnPtr>::ReturnType>
319 struct CallConstMember
321 typedef typename FuncTraits <MemFnPtr>::ClassType T;
322 typedef typename FuncTraits <MemFnPtr>::Params Params;
324 static int f (lua_State* L)
326 assert (isfulluserdata (L, lua_upvalueindex (1)));
327 T const* const t = Userdata::get <T> (L, 1, true);
328 MemFnPtr const& fnptr = *static_cast <MemFnPtr const*> (lua_touserdata (L, lua_upvalueindex (1)));
330 ArgList <Params, 2> args(L);
331 Stack <ReturnType>::push (L, FuncTraits <MemFnPtr>::call (t, fnptr, args));
336 template <class MemFnPtr, class T,
337 class ReturnType = typename FuncTraits <MemFnPtr>::ReturnType>
340 typedef typename FuncTraits <MemFnPtr>::Params Params;
342 static int f (lua_State* L)
344 assert (isfulluserdata (L, lua_upvalueindex (1)));
345 boost::shared_ptr<T>* const t = Userdata::get <boost::shared_ptr<T> > (L, 1, false);
346 T* const tt = t->get();
348 return luaL_error (L, "shared_ptr is nil");
350 MemFnPtr const& fnptr = *static_cast <MemFnPtr const*> (lua_touserdata (L, lua_upvalueindex (1)));
352 ArgList <Params, 2> args (L);
353 Stack <ReturnType>::push (L, FuncTraits <MemFnPtr>::call (tt, fnptr, args));
358 template <class T, class R>
361 static int f (lua_State* L)
363 boost::shared_ptr<T> t = luabridge::Stack<boost::shared_ptr<T> >::get (L, 1);
364 Stack <boost::shared_ptr<R> >::push (L, boost::dynamic_pointer_cast<R> (t));
372 static int f (lua_State* L)
374 boost::shared_ptr<T> t = luabridge::Stack<boost::shared_ptr<T> >::get (L, 1);
375 Stack <bool>::push (L, t == 0);
383 static int f (lua_State* L)
386 boost::weak_ptr<T> tw = luabridge::Stack<boost::weak_ptr<T> >::get (L, 1);
387 boost::shared_ptr<T> const t = tw.lock();
389 T* const tt = t.get();
392 Stack <bool>::push (L, rv);
397 template <class MemFnPtr, class T,
398 class ReturnType = typename FuncTraits <MemFnPtr>::ReturnType>
399 struct CallMemberWPtr
401 typedef typename FuncTraits <MemFnPtr>::Params Params;
403 static int f (lua_State* L)
405 assert (isfulluserdata (L, lua_upvalueindex (1)));
406 boost::weak_ptr<T>* const tw = Userdata::get <boost::weak_ptr<T> > (L, 1, false);
407 boost::shared_ptr<T> const t = tw->lock();
409 return luaL_error (L, "cannot lock weak_ptr");
411 T* const tt = t.get();
413 return luaL_error (L, "weak_ptr is nil");
415 MemFnPtr const& fnptr = *static_cast <MemFnPtr const*> (lua_touserdata (L, lua_upvalueindex (1)));
417 ArgList <Params, 2> args (L);
418 Stack <ReturnType>::push (L, FuncTraits <MemFnPtr>::call (tt, fnptr, args));
424 lua_CFunction to calls for function references.
426 template <class MemFnPtr,
427 class ReturnType = typename FuncTraits <MemFnPtr>::ReturnType>
430 typedef typename FuncTraits <MemFnPtr>::ClassType T;
431 typedef typename FuncTraits <MemFnPtr>::Params Params;
433 static int f (lua_State* L)
435 assert (isfulluserdata (L, lua_upvalueindex (1)));
436 T* const t = Userdata::get <T> (L, 1, false);
437 MemFnPtr const& fnptr = *static_cast <MemFnPtr const*> (lua_touserdata (L, lua_upvalueindex (1)));
439 ArgList <Params, 2> args (L);
440 Stack <ReturnType>::push (L, FuncTraits <MemFnPtr>::call (t, fnptr, args));
441 LuaRef v (newTable (L));
442 FuncArgs <Params, 0>::refs (v, args);
448 template <class MemFnPtr,
449 class ReturnType = typename FuncTraits <MemFnPtr>::ReturnType>
450 struct CallConstMemberRef
452 typedef typename FuncTraits <MemFnPtr>::ClassType T;
453 typedef typename FuncTraits <MemFnPtr>::Params Params;
455 static int f (lua_State* L)
457 assert (isfulluserdata (L, lua_upvalueindex (1)));
458 T const* const t = Userdata::get <T> (L, 1, true);
459 MemFnPtr const& fnptr = *static_cast <MemFnPtr const*> (lua_touserdata (L, lua_upvalueindex (1)));
461 ArgList <Params, 2> args(L);
462 Stack <ReturnType>::push (L, FuncTraits <MemFnPtr>::call (t, fnptr, args));
463 LuaRef v (newTable (L));
464 FuncArgs <Params, 0>::refs (v, args);
470 template <class MemFnPtr, class T,
471 class ReturnType = typename FuncTraits <MemFnPtr>::ReturnType>
472 struct CallMemberRefPtr
474 typedef typename FuncTraits <MemFnPtr>::Params Params;
476 static int f (lua_State* L)
478 assert (isfulluserdata (L, lua_upvalueindex (1)));
479 boost::shared_ptr<T>* const t = Userdata::get <boost::shared_ptr<T> > (L, 1, false);
480 T* const tt = t->get();
482 return luaL_error (L, "shared_ptr is nil");
484 MemFnPtr const& fnptr = *static_cast <MemFnPtr const*> (lua_touserdata (L, lua_upvalueindex (1)));
486 ArgList <Params, 2> args (L);
487 Stack <ReturnType>::push (L, FuncTraits <MemFnPtr>::call (tt, fnptr, args));
488 LuaRef v (newTable (L));
489 FuncArgs <Params, 0>::refs (v, args);
495 template <class MemFnPtr, class T,
496 class ReturnType = typename FuncTraits <MemFnPtr>::ReturnType>
497 struct CallMemberRefWPtr
499 typedef typename FuncTraits <MemFnPtr>::Params Params;
501 static int f (lua_State* L)
503 assert (isfulluserdata (L, lua_upvalueindex (1)));
504 boost::weak_ptr<T>* const tw = Userdata::get <boost::weak_ptr<T> > (L, 1, false);
505 boost::shared_ptr<T> const t = tw->lock();
507 return luaL_error (L, "cannot lock weak_ptr");
509 T* const tt = t.get();
511 return luaL_error (L, "weak_ptr is nil");
513 MemFnPtr const& fnptr = *static_cast <MemFnPtr const*> (lua_touserdata (L, lua_upvalueindex (1)));
515 ArgList <Params, 2> args (L);
516 Stack <ReturnType>::push (L, FuncTraits <MemFnPtr>::call (tt, fnptr, args));
517 LuaRef v (newTable (L));
518 FuncArgs <Params, 0>::refs (v, args);
524 //----------------------------------------------------------------------------
526 lua_CFunction to call a class member function with no return value.
528 The member function pointer is in the first upvalue.
529 The class userdata object is at the top of the Lua stack.
531 template <class MemFnPtr>
532 struct CallMember <MemFnPtr, void>
534 typedef typename FuncTraits <MemFnPtr>::ClassType T;
535 typedef typename FuncTraits <MemFnPtr>::Params Params;
537 static int f (lua_State* L)
539 assert (isfulluserdata (L, lua_upvalueindex (1)));
540 T* const t = Userdata::get <T> (L, 1, false);
541 MemFnPtr const& fnptr = *static_cast <MemFnPtr const*> (lua_touserdata (L, lua_upvalueindex (1)));
543 ArgList <Params, 2> args (L);
544 FuncTraits <MemFnPtr>::call (t, fnptr, args);
549 template <class MemFnPtr>
550 struct CallConstMember <MemFnPtr, void>
552 typedef typename FuncTraits <MemFnPtr>::ClassType T;
553 typedef typename FuncTraits <MemFnPtr>::Params Params;
555 static int f (lua_State* L)
557 assert (isfulluserdata (L, lua_upvalueindex (1)));
558 T const* const t = Userdata::get <T> (L, 1, true);
559 MemFnPtr const& fnptr = *static_cast <MemFnPtr const*> (lua_touserdata (L, lua_upvalueindex (1)));
561 ArgList <Params, 2> args (L);
562 FuncTraits <MemFnPtr>::call (t, fnptr, args);
567 template <class MemFnPtr, class T>
568 struct CallMemberPtr <MemFnPtr, T, void>
570 typedef typename FuncTraits <MemFnPtr>::Params Params;
572 static int f (lua_State* L)
574 assert (isfulluserdata (L, lua_upvalueindex (1)));
575 boost::shared_ptr<T>* const t = Userdata::get <boost::shared_ptr<T> > (L, 1, false);
576 T* const tt = t->get();
577 MemFnPtr const& fnptr = *static_cast <MemFnPtr const*> (lua_touserdata (L, lua_upvalueindex (1)));
579 ArgList <Params, 2> args (L);
580 FuncTraits <MemFnPtr>::call (tt, fnptr, args);
585 template <class MemFnPtr, class T>
586 struct CallMemberWPtr <MemFnPtr, T, void>
588 typedef typename FuncTraits <MemFnPtr>::Params Params;
590 static int f (lua_State* L)
592 assert (isfulluserdata (L, lua_upvalueindex (1)));
593 boost::weak_ptr<T>* const tw = Userdata::get <boost::weak_ptr<T> > (L, 1, false);
594 boost::shared_ptr<T> const t = tw->lock();
596 return luaL_error (L, "cannot lock weak_ptr");
598 T* const tt = t.get();
600 return luaL_error (L, "weak_ptr is nil");
602 MemFnPtr const& fnptr = *static_cast <MemFnPtr const*> (lua_touserdata (L, lua_upvalueindex (1)));
604 ArgList <Params, 2> args (L);
605 FuncTraits <MemFnPtr>::call (tt, fnptr, args);
610 template <class MemFnPtr>
611 struct CallMemberRef <MemFnPtr, void>
613 typedef typename FuncTraits <MemFnPtr>::ClassType T;
614 typedef typename FuncTraits <MemFnPtr>::Params Params;
616 static int f (lua_State* L)
618 assert (isfulluserdata (L, lua_upvalueindex (1)));
619 T* const t = Userdata::get <T> (L, 1, false);
620 MemFnPtr const& fnptr = *static_cast <MemFnPtr const*> (lua_touserdata (L, lua_upvalueindex (1)));
622 ArgList <Params, 2> args (L);
623 FuncTraits <MemFnPtr>::call (t, fnptr, args);
624 LuaRef v (newTable (L));
625 FuncArgs <Params, 0>::refs (v, args);
631 template <class MemFnPtr>
632 struct CallConstMemberRef <MemFnPtr, void>
634 typedef typename FuncTraits <MemFnPtr>::ClassType T;
635 typedef typename FuncTraits <MemFnPtr>::Params Params;
637 static int f (lua_State* L)
639 assert (isfulluserdata (L, lua_upvalueindex (1)));
640 T const* const t = Userdata::get <T> (L, 1, true);
641 MemFnPtr const& fnptr = *static_cast <MemFnPtr const*> (lua_touserdata (L, lua_upvalueindex (1)));
643 ArgList <Params, 2> args (L);
644 FuncTraits <MemFnPtr>::call (t, fnptr, args);
645 LuaRef v (newTable (L));
646 FuncArgs <Params, 0>::refs (v, args);
652 template <class MemFnPtr, class T>
653 struct CallMemberRefPtr <MemFnPtr, T, void>
655 typedef typename FuncTraits <MemFnPtr>::Params Params;
657 static int f (lua_State* L)
659 assert (isfulluserdata (L, lua_upvalueindex (1)));
660 boost::shared_ptr<T>* const t = Userdata::get <boost::shared_ptr<T> > (L, 1, false);
661 T* const tt = t->get();
663 return luaL_error (L, "shared_ptr is nil");
665 MemFnPtr const& fnptr = *static_cast <MemFnPtr const*> (lua_touserdata (L, lua_upvalueindex (1)));
667 ArgList <Params, 2> args (L);
668 FuncTraits <MemFnPtr>::call (tt, fnptr, args);
669 LuaRef v (newTable (L));
670 FuncArgs <Params, 0>::refs (v, args);
676 template <class MemFnPtr, class T>
677 struct CallMemberRefWPtr <MemFnPtr, T, void>
679 typedef typename FuncTraits <MemFnPtr>::Params Params;
681 static int f (lua_State* L)
683 assert (isfulluserdata (L, lua_upvalueindex (1)));
684 boost::weak_ptr<T>* const tw = Userdata::get <boost::weak_ptr<T> > (L, 1, false);
685 boost::shared_ptr<T> const t = tw->lock();
687 return luaL_error (L, "cannot lock weak_ptr");
689 T* const tt = t.get();
691 return luaL_error (L, "weak_ptr is nil");
693 MemFnPtr const& fnptr = *static_cast <MemFnPtr const*> (lua_touserdata (L, lua_upvalueindex (1)));
695 ArgList <Params, 2> args (L);
696 FuncTraits <MemFnPtr>::call (tt, fnptr, args);
697 LuaRef v (newTable (L));
698 FuncArgs <Params, 0>::refs (v, args);
704 //--------------------------------------------------------------------------
706 lua_CFunction to call a class member lua_CFunction.
708 The member function pointer is in the first upvalue.
709 The class userdata object is at the top of the Lua stack.
712 struct CallMemberCFunction
714 static int f (lua_State* L)
716 assert (isfulluserdata (L, lua_upvalueindex (1)));
717 typedef int (T::*MFP)(lua_State* L);
718 T* const t = Userdata::get <T> (L, 1, false);
719 MFP const& fnptr = *static_cast <MFP const*> (lua_touserdata (L, lua_upvalueindex (1)));
721 return (t->*fnptr) (L);
726 struct CallConstMemberCFunction
728 static int f (lua_State* L)
730 assert (isfulluserdata (L, lua_upvalueindex (1)));
731 typedef int (T::*MFP)(lua_State* L);
732 T const* const t = Userdata::get <T> (L, 1, true);
733 MFP const& fnptr = *static_cast <MFP const*> (lua_touserdata (L, lua_upvalueindex (1)));
735 return (t->*fnptr) (L);
739 //--------------------------------------------------------------------------
743 template <class MemFnPtr, bool isConst>
744 struct CallMemberFunctionHelper
746 static void add (lua_State* L, char const* name, MemFnPtr mf)
748 new (lua_newuserdata (L, sizeof (MemFnPtr))) MemFnPtr (mf);
749 lua_pushcclosure (L, &CallConstMember <MemFnPtr>::f, 1);
750 lua_pushvalue (L, -1);
751 rawsetfield (L, -5, name); // const table
752 rawsetfield (L, -3, name); // class table
756 template <class MemFnPtr>
757 struct CallMemberFunctionHelper <MemFnPtr, false>
759 static void add (lua_State* L, char const* name, MemFnPtr mf)
761 new (lua_newuserdata (L, sizeof (MemFnPtr))) MemFnPtr (mf);
762 lua_pushcclosure (L, &CallMember <MemFnPtr>::f, 1);
763 rawsetfield (L, -3, name); // class table
767 template <class MemFnPtr>
768 struct CallMemberPtrFunctionHelper
770 typedef typename FuncTraits <MemFnPtr>::ClassType T;
771 static void add (lua_State* L, char const* name, MemFnPtr mf)
773 new (lua_newuserdata (L, sizeof (MemFnPtr))) MemFnPtr (mf);
774 lua_pushcclosure (L, &CallMemberPtr <MemFnPtr, T>::f, 1);
775 rawsetfield (L, -3, name); // class table
779 template <class MemFnPtr>
780 struct CallMemberRefPtrFunctionHelper
782 typedef typename FuncTraits <MemFnPtr>::ClassType T;
783 static void add (lua_State* L, char const* name, MemFnPtr mf)
785 new (lua_newuserdata (L, sizeof (MemFnPtr))) MemFnPtr (mf);
786 lua_pushcclosure (L, &CallMemberRefPtr <MemFnPtr, T>::f, 1);
787 rawsetfield (L, -3, name); // class table
791 template <class MemFnPtr>
792 struct CallMemberWPtrFunctionHelper
794 typedef typename FuncTraits <MemFnPtr>::ClassType T;
795 static void add (lua_State* L, char const* name, MemFnPtr mf)
797 new (lua_newuserdata (L, sizeof (MemFnPtr))) MemFnPtr (mf);
798 lua_pushcclosure (L, &CallMemberWPtr <MemFnPtr, T>::f, 1);
799 rawsetfield (L, -3, name); // class table
803 template <class MemFnPtr>
804 struct CallMemberRefWPtrFunctionHelper
806 typedef typename FuncTraits <MemFnPtr>::ClassType T;
807 static void add (lua_State* L, char const* name, MemFnPtr mf)
809 new (lua_newuserdata (L, sizeof (MemFnPtr))) MemFnPtr (mf);
810 lua_pushcclosure (L, &CallMemberRefWPtr <MemFnPtr, T>::f, 1);
811 rawsetfield (L, -3, name); // class table
815 template <class MemFnPtr, bool isConst>
816 struct CallMemberRefFunctionHelper
818 static void add (lua_State* L, char const* name, MemFnPtr mf)
820 new (lua_newuserdata (L, sizeof (MemFnPtr))) MemFnPtr (mf);
821 lua_pushcclosure (L, &CallConstMemberRef <MemFnPtr>::f, 1);
822 lua_pushvalue (L, -1);
823 rawsetfield (L, -5, name); // const table
824 rawsetfield (L, -3, name); // class table
828 template <class MemFnPtr>
829 struct CallMemberRefFunctionHelper <MemFnPtr, false>
831 static void add (lua_State* L, char const* name, MemFnPtr mf)
833 new (lua_newuserdata (L, sizeof (MemFnPtr))) MemFnPtr (mf);
834 lua_pushcclosure (L, &CallMemberRef <MemFnPtr>::f, 1);
835 rawsetfield (L, -3, name); // class table
839 //--------------------------------------------------------------------------
841 __gc metamethod for a class.
844 static int gcMetaMethod (lua_State* L)
846 Userdata* const ud = Userdata::getExact <C> (L, 1);
851 static int gcNOOPMethod (lua_State* L)
856 //--------------------------------------------------------------------------
858 lua_CFunction to get a class data member.
860 The pointer-to-member is in the first upvalue.
861 The class userdata object is at the top of the Lua stack.
863 template <class C, typename T>
864 static int getProperty (lua_State* L)
866 C const* const c = Userdata::get <C> (L, 1, true);
867 T C::** mp = static_cast <T C::**> (lua_touserdata (L, lua_upvalueindex (1)));
868 Stack <T>::push (L, c->**mp);
872 //--------------------------------------------------------------------------
875 lua_CFunction to get a constant (enum)
877 template <typename U>
878 static int getConst (lua_State* L)
880 U *v = static_cast <U *> (lua_touserdata (L, lua_upvalueindex (1)));
882 Stack <U>::push (L, *v);
886 //--------------------------------------------------------------------------
888 lua_CFunction to set a class data member.
890 The pointer-to-member is in the first upvalue.
891 The class userdata object is at the top of the Lua stack.
893 template <class C, typename T>
894 static int setProperty (lua_State* L)
896 C* const c = Userdata::get <C> (L, 1, false);
897 T C::** mp = static_cast <T C::**> (lua_touserdata (L, lua_upvalueindex (1)));
898 c->**mp = Stack <T>::get (L, 2);
902 //--------------------------------------------------------------------------
904 // metatable callback for "array[index]"
905 template <typename T>
906 static int array_index (lua_State* L) {
907 T** parray = (T**) luaL_checkudata (L, 1, typeid(T).name());
908 int const index = luabridge::Stack<int>::get (L, 2);
909 luabridge::Stack<T>::push (L, (*parray)[index-1]);
913 // metatable callback for "array[index] = value"
914 template <typename T>
915 static int array_newindex (lua_State* L) {
916 T** parray = (T**) luaL_checkudata (L, 1, typeid(T).name());
917 int const index = luabridge::Stack<int>::get (L, 2);
918 T const value = luabridge::Stack<T>::get (L, 3);
919 (*parray)[index-1] = value;
923 template <typename T>
924 static int getArray (lua_State* L) {
925 T *v = luabridge::Stack<T*>::get (L, 1);
926 T** parray = (T**) lua_newuserdata(L, sizeof(T**));
928 luaL_getmetatable(L, typeid(T).name());
929 lua_setmetatable(L, -2);
933 // copy complete c array to lua table
934 template <typename T>
935 static int getTable (lua_State* L) {
936 T *v = luabridge::Stack<T*>::get (L, 1);
937 const int cnt = luabridge::Stack<int>::get (L, 2);
940 for (int i = 0; i < cnt; ++i) {
947 // copy lua table to c array
948 template <typename T>
949 static int setTable (lua_State* L) {
950 T *v = luabridge::Stack<T*>::get (L, 1);
951 LuaRef t (LuaRef::fromStack(L, 2));
952 const int cnt = luabridge::Stack<int>::get (L, 3);
953 for (int i = 0; i < cnt; ++i) {
960 //--------------------------------------------------------------------------
965 // read lua table into C++ std::list
966 template <class T, class C>
967 static int tableToListHelper (lua_State *L, C * const t)
969 if (!t) { return luaL_error (L, "invalid pointer to std::list<>/std::vector"); }
970 if (!lua_istable (L, -1)) { return luaL_error (L, "argument is not a table"); }
971 lua_pushvalue (L, -1);
973 while (lua_next (L, -2)) {
974 lua_pushvalue (L, -2);
975 T const value = Stack<T>::get (L, -2);
976 t->push_back (value);
981 Stack<C>::push (L, *t);
985 template <class T, class C>
986 static int tableToList (lua_State *L)
988 C * const t = Userdata::get<C> (L, 1, false);
989 return tableToListHelper<T, C> (L, t);
992 template <class T, class C>
993 static int ptrTableToList (lua_State *L)
995 boost::shared_ptr<C> const* const t = Userdata::get<boost::shared_ptr<C> > (L, 1, true);
996 if (!t) { return luaL_error (L, "cannot derefencee shared_ptr"); }
997 return tableToListHelper<T, C> (L, t->get());
1000 //--------------------------------------------------------------------------
1001 template <class T, class C>
1002 static int listIterIter (lua_State *L) {
1003 typedef typename C::const_iterator IterType;
1004 IterType * const end = static_cast <IterType * const> (lua_touserdata (L, lua_upvalueindex (2)));
1005 IterType * const iter = static_cast <IterType * const> (lua_touserdata (L, lua_upvalueindex (1)));
1008 if ((*iter) == (*end)) {
1011 Stack <T>::push (L, **iter);
1016 // generate an iterator
1017 template <class T, class C>
1018 static int listIterHelper (lua_State *L, C * const t)
1020 if (!t) { return luaL_error (L, "invalid pointer to std::list<>/std::vector"); }
1021 typedef typename C::const_iterator IterType;
1022 new (lua_newuserdata (L, sizeof (IterType*))) IterType (t->begin());
1023 new (lua_newuserdata (L, sizeof (IterType*))) IterType (t->end());
1024 lua_pushcclosure (L, listIterIter<T, C>, 2);
1028 template <class T, class C>
1029 static int listIter (lua_State *L)
1031 C * const t = Userdata::get <C> (L, 1, false);
1032 return listIterHelper<T, C> (L, t);
1035 template <class T, class C>
1036 static int ptrListIter (lua_State *L)
1038 boost::shared_ptr<C> const* const t = Userdata::get <boost::shared_ptr<C> >(L, 1, true);
1039 if (!t) { return luaL_error (L, "cannot derefencee shared_ptr"); }
1040 return listIterHelper<T, C> (L, t->get());
1043 //--------------------------------------------------------------------------
1044 // generate table from std::list
1045 template <class T, class C>
1046 static int listToTableHelper (lua_State *L, C const* const t)
1048 if (!t) { return luaL_error (L, "invalid pointer to std::list<>/std::vector"); }
1049 #if 0 // direct lua api
1050 lua_createtable(L, t->size(), 0);
1051 int newTable = lua_gettop(L);
1053 for (typename C::const_iterator iter = t->begin(); iter != t->end(); ++iter, ++index) {
1054 Stack<T>::push(L, (*iter));
1055 lua_rawseti (L, newTable, index);
1057 #else // luabridge way
1061 for (typename C::const_iterator iter = t->begin(); iter != t->end(); ++iter, ++index) {
1069 template <class T, class C>
1070 static int listToTable (lua_State *L)
1072 C const* const t = Userdata::get <C> (L, 1, true);
1073 return listToTableHelper<T, C> (L, t);
1076 template <class T, class C>
1077 static int ptrListToTable (lua_State *L)
1079 boost::shared_ptr<C> const* const t = Userdata::get <boost::shared_ptr<C> > (L, 1, true);
1080 if (!t) { return luaL_error (L, "cannot derefencee shared_ptr"); }
1081 return listToTableHelper<T, C> (L, t->get());
1084 //--------------------------------------------------------------------------
1085 // generate std::map from table
1087 template <class K, class V>
1088 static int tableToMap (lua_State *L)
1090 typedef std::map<K, V> C;
1091 C * const t = Userdata::get <C> (L, 1, true);
1092 if (!t) { return luaL_error (L, "invalid pointer to std::map"); }
1093 if (!lua_istable (L, -1)) { return luaL_error (L, "argument is not a table"); }
1095 lua_pushvalue (L, -1);
1097 while (lua_next (L, -2)) {
1098 lua_pushvalue (L, -2);
1099 K const key = Stack<K>::get (L, -1);
1100 V const value = Stack<V>::get (L, -2);
1101 t->insert (std::pair<K,V> (key, value));
1102 //(*t)[key] = value;
1107 Stack<C>::push (L, *t);
1111 // iterate over a std::map
1112 template <class K, class V>
1113 static int mapIterIter (lua_State *L)
1115 typedef std::map<K, V> C;
1116 typedef typename C::const_iterator IterType;
1117 IterType * const end = static_cast <IterType * const> (lua_touserdata (L, lua_upvalueindex (2)));
1118 IterType * const iter = static_cast <IterType * const> (lua_touserdata (L, lua_upvalueindex (1)));
1121 if ((*iter) == (*end)) {
1124 Stack <K>::push (L, (*iter)->first);
1125 Stack <V>::push (L, (*iter)->second);
1130 // generate iterator
1131 template <class K, class V>
1132 static int mapIter (lua_State *L)
1134 typedef std::map<K, V> C;
1135 C * const t = Userdata::get <C> (L, 1, false);
1136 if (!t) { return luaL_error (L, "invalid pointer to std::map"); }
1137 typedef typename C::const_iterator IterType;
1138 new (lua_newuserdata (L, sizeof (IterType*))) IterType (t->begin());
1139 new (lua_newuserdata (L, sizeof (IterType*))) IterType (t->end());
1140 lua_pushcclosure (L, mapIterIter<K, V>, 2);
1144 // generate table from std::map
1145 template <class K, class V>
1146 static int mapToTable (lua_State *L)
1148 typedef std::map<K, V> C;
1149 C const* const t = Userdata::get <C> (L, 1, true);
1150 if (!t) { return luaL_error (L, "invalid pointer to std::map"); }
1154 for (typename C::const_iterator iter = t->begin(); iter != t->end(); ++iter) {
1155 v[(*iter).first] = (*iter).second;
1161 //--------------------------------------------------------------------------
1162 // generate std::set from table keys ( table[member] = true )
1163 // http://www.lua.org/pil/11.5.html
1166 static int tableToSet (lua_State *L)
1168 typedef std::set<T> C;
1169 C * const t = Userdata::get <C> (L, 1, true);
1170 if (!t) { return luaL_error (L, "invalid pointer to std::set"); }
1171 if (!lua_istable (L, -1)) { return luaL_error (L, "argument is not a table"); }
1173 lua_pushvalue (L, -1);
1175 while (lua_next (L, -2)) {
1176 lua_pushvalue (L, -2);
1177 T const member = Stack<T>::get (L, -1);
1178 bool const v = Stack<bool>::get (L, -2);
1186 Stack<C>::push (L, *t);
1190 // iterate over a std::set, explicit "true" value.
1191 // compare to http://www.lua.org/pil/11.5.html
1193 static int setIterIter (lua_State *L)
1195 typedef std::set<T> C;
1196 typedef typename C::const_iterator IterType;
1197 IterType * const end = static_cast <IterType * const> (lua_touserdata (L, lua_upvalueindex (2)));
1198 IterType * const iter = static_cast <IterType * const> (lua_touserdata (L, lua_upvalueindex (1)));
1201 if ((*iter) == (*end)) {
1204 Stack <T>::push (L, **iter);
1205 Stack <bool>::push (L, true);
1210 // generate iterator
1212 static int setIter (lua_State *L)
1214 typedef std::set<T> C;
1215 C * const t = Userdata::get <C> (L, 1, false);
1216 if (!t) { return luaL_error (L, "invalid pointer to std::set"); }
1217 typedef typename C::const_iterator IterType;
1218 new (lua_newuserdata (L, sizeof (IterType*))) IterType (t->begin());
1219 new (lua_newuserdata (L, sizeof (IterType*))) IterType (t->end());
1220 lua_pushcclosure (L, setIterIter<T>, 2);
1224 // generate table from std::set
1226 static int setToTable (lua_State *L)
1228 typedef std::set<T> C;
1229 C const* const t = Userdata::get <C> (L, 1, true);
1230 if (!t) { return luaL_error (L, "invalid pointer to std::set"); }
1234 for (typename C::const_iterator iter = t->begin(); iter != t->end(); ++iter) {
1241 //--------------------------------------------------------------------------
1242 // bitset { num = true }
1243 // compare to http://www.lua.org/pil/11.5.html
1244 template <unsigned int T>
1245 static int tableToBitSet (lua_State *L)
1247 typedef std::bitset<T> C;
1248 C * const t = Userdata::get <C> (L, 1, true);
1249 if (!t) { return luaL_error (L, "invalid pointer to std::bitset"); }
1250 if (!lua_istable (L, -1)) { return luaL_error (L, "argument is not a table"); }
1252 lua_pushvalue (L, -1);
1254 while (lua_next (L, -2)) {
1255 lua_pushvalue (L, -2);
1256 unsigned int const member = Stack<unsigned int>::get (L, -1);
1257 bool const v = Stack<bool>::get (L, -2);
1258 if (member < T && v) {
1265 Stack<C>::push (L, *t);
1269 // generate table from std::bitset
1270 template <unsigned int T>
1271 static int bitSetToTable (lua_State *L)
1273 typedef std::bitset<T> C;
1274 C const* const t = Userdata::get <C> (L, 1, true);
1275 if (!t) { return luaL_error (L, "invalid pointer to std::bitset"); }
1279 for (unsigned int i = 0; i < T; ++i) {
1290 /* vim: set et sw=2: */