1 //------------------------------------------------------------------------------
2 /*
3 https://github.com/vinniefalco/LuaBridge
4
5 Copyright 2016, Robin Gareus <robin@gareus.org>
6 Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
7 Copyright 2007, Nathan Reed
8
9 License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
10
11 Permission is hereby granted, free of charge, to any person obtaining a copy
12 of this software and associated documentation files (the "Software"), to deal
13 in the Software without restriction, including without limitation the rights
14 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 copies of the Software, and to permit persons to whom the Software is
16 furnished to do so, subject to the following conditions:
17
18 The above copyright notice and this permission notice shall be included in all
19 copies or substantial portions of the Software.
20
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 SOFTWARE.
28 */
29 //==============================================================================
30
31 #ifdef LUABINDINGDOC
32 #include <iostream>
33 #include <typeinfo>
34 #include <execinfo.h>
35 #include <type_traits>
36 #include <cxxabi.h>
37 #include <memory>
38 #include <string>
39 #include <cstdlib>
40
41 template <class T>
type_name()42 std::string type_name()
43 {
44 typedef typename std::remove_reference<T>::type TR;
45 std::unique_ptr<char, void(*)(void*)> own
46 (
47 abi::__cxa_demangle(typeid(TR).name(), nullptr,
48 nullptr, nullptr),
49 std::free
50 );
51 std::string r = own != nullptr ? own.get() : typeid(TR).name();
52 if (std::is_const<TR>::value)
53 r += " const";
54 if (std::is_volatile<TR>::value)
55 r += " volatile";
56 if (std::is_lvalue_reference<T>::value)
57 r += "&";
58 else if (std::is_rvalue_reference<T>::value)
59 r += "&&";
60 return r;
61 }
62
63 //#define LUADOCOUT
64
65 #ifdef LUADOCOUT // lua
66 #define KEYSTA "[\""
67 #define KEYEND "\"] = "
68 #else // JSON
69 #define KEYSTA "\""
70 #define KEYEND "\" : "
71 #endif
72
73 #define CLASSDOC(TYPE, LUANAME, DECL, PARENTDECL) \
74 if (LuaBindingDoc::printBindings ()) { \
75 std::cout << "{ " << KEYSTA << "type" << KEYEND << " \"" << TYPE << "\",\n"; \
76 std::cout << " " << KEYSTA << "lua" << KEYEND << " \"" << LUANAME << "\",\n"; \
77 std::cout << " " << KEYSTA << "decl" << KEYEND << " \"" << DECL << "\",\n"; \
78 std::cout << " " << KEYSTA << "parent" << KEYEND << "\"" << PARENTDECL << "\"\n"; \
79 std::cout << "},\n"; \
80 }
81
82 #define PRINTDOC(TYPE, LUANAME, RETVAL, DECL) \
83 if (LuaBindingDoc::printBindings ()) { \
84 std::cout << "{ " << KEYSTA << "type" << KEYEND << " \"" << TYPE << "\",\n"; \
85 std::cout << " " << KEYSTA << "lua" << KEYEND << " \"" << LUANAME << "\",\n"; \
86 if (!(RETVAL).empty()) { \
87 std::cout << " " << KEYSTA << "ret" << KEYEND << " \"" << (RETVAL) << "\",\n"; \
88 } \
89 std::cout << " " << KEYSTA << "decl" << KEYEND << " \"" << DECL << "\"\n"; \
90 std::cout << "},\n"; \
91 }
92
93 #define FUNDOC(TYPE, NAME, FUNCTOR) \
94 PRINTDOC(TYPE, _name << NAME, \
95 type_name< typename FuncTraits <FUNCTOR>::ReturnType >(), \
96 type_name< typename FuncTraits <FUNCTOR>::DeclType >())
97
98 #define DATADOC(TYPE, NAME, FUNCTOR) \
99 PRINTDOC(TYPE, _name << NAME, \
100 std::string(), \
101 type_name< decltype(FUNCTOR) >())\
102
103
104 #else
105
106 #define CLASSDOC(TYPE, LUANAME, DECL, PARENTDECL)
107 #define PRINTDOC(TYPE, LUANAME, RETVAL, DECL)
108 #define FUNDOC(TYPE, NAME, FUNCTOR)
109 #define DATADOC(TYPE, NAME, FUNCTOR)
110
111 #endif
112
113 /** Provides C++ to Lua registration capabilities.
114
115 This class is not instantiated directly, call `getGlobalNamespace` to start
116 the registration process.
117 */
118 class Namespace
119 {
120 private:
121 Namespace& operator= (Namespace const& other);
122
123 lua_State* const L;
124 int mutable m_stackSize;
125
126 private:
127 //============================================================================
128 /**
129 Error reporting.
130
131 VF: This function looks handy, why aren't we using it?
132 */
133 #if 0
134 static int luaError (lua_State* L, std::string message)
135 {
136 assert (lua_isstring (L, lua_upvalueindex (1)));
137 std::string s;
138
139 // Get information on the caller's caller to format the message,
140 // so the error appears to originate from the Lua source.
141 lua_Debug ar;
142 int result = lua_getstack (L, 2, &ar);
143 if (result != 0)
144 {
145 lua_getinfo (L, "Sl", &ar);
146 s = ar.short_src;
147 if (ar.currentline != -1)
148 {
149 // poor mans int to string to avoid <strstrream>.
150 lua_pushnumber (L, ar.currentline);
151 s = s + ":" + lua_tostring (L, -1) + ": ";
152 lua_pop (L, 1);
153 }
154 }
155
156 s = s + message;
157
158 return luaL_error (L, s.c_str ());
159 }
160 #endif
161
162 //----------------------------------------------------------------------------
163 /**
164 Pop the Lua stack.
165 */
pop(int n)166 void pop (int n) const
167 {
168 if (m_stackSize >= n && lua_gettop (L) >= n)
169 {
170 lua_pop (L, n);
171 m_stackSize -= n;
172 }
173 else
174 {
175 throw std::logic_error ("invalid stack");
176 }
177 }
178
179 private:
180 /**
181 Factored base to reduce template instantiations.
182 */
183 class ClassBase
184 {
185 private:
186 ClassBase& operator= (ClassBase const& other);
187
188 protected:
189 friend class Namespace;
190
191 lua_State* const L;
192 int mutable m_stackSize;
193
194 #ifdef LUABINDINGDOC
195 std::string _name;
196 const Namespace* _parent;
197 #endif
198
199 protected:
200 //--------------------------------------------------------------------------
201 /**
202 __index metamethod for a class.
203
204 This implements member functions, data members, and property members.
205 Functions are stored in the metatable and const metatable. Data members
206 and property members are in the __propget table.
207
208 If the key is not found, the search proceeds up the hierarchy of base
209 classes.
210 */
indexMetaMethod(lua_State * L)211 static int indexMetaMethod (lua_State* L)
212 {
213 int result = 0;
214
215 assert (lua_isuserdata (L, 1)); // warn on security bypass
216 lua_getmetatable (L, 1); // get metatable for object
217 for (;;)
218 {
219 lua_pushvalue (L, 2); // push key arg2
220 lua_rawget (L, -2); // lookup key in metatable
221 if (lua_iscfunction (L, -1)) // ensure its a cfunction
222 {
223 lua_remove (L, -2); // remove metatable
224 result = 1;
225 break;
226 }
227 else if (lua_isnil (L, -1))
228 {
229 lua_pop (L, 1);
230 }
231 else
232 {
233 lua_pop (L, 2);
234 throw std::logic_error ("not a cfunction");
235 }
236
237 rawgetfield (L, -1, "__propget"); // get __propget table
238 if (lua_istable (L, -1)) // ensure it is a table
239 {
240 lua_pushvalue (L, 2); // push key arg2
241 lua_rawget (L, -2); // lookup key in __propget
242 lua_remove (L, -2); // remove __propget
243 if (lua_iscfunction (L, -1)) // ensure its a cfunction
244 {
245 lua_remove (L, -2); // remove metatable
246 lua_pushvalue (L, 1); // push class arg1
247 lua_call (L, 1, 1);
248 result = 1;
249 break;
250 }
251 else if (lua_isnil (L, -1))
252 {
253 lua_pop (L, 1);
254 }
255 else
256 {
257 lua_pop (L, 2);
258
259 // We only put cfunctions into __propget.
260 throw std::logic_error ("not a cfunction");
261 }
262 }
263 else
264 {
265 lua_pop (L, 2);
266
267 // __propget is missing, or not a table.
268 throw std::logic_error ("missing __propget table");
269 }
270
271 // Repeat the lookup in the __parent metafield,
272 // or return nil if the field doesn't exist.
273 rawgetfield (L, -1, "__parent");
274 if (lua_istable (L, -1))
275 {
276 // Remove metatable and repeat the search in __parent.
277 lua_remove (L, -2);
278 }
279 else if (lua_isnil (L, -1))
280 {
281 result = 1;
282 break;
283 }
284 else
285 {
286 lua_pop (L, 2);
287
288 throw std::logic_error ("__parent is not a table");
289 }
290 }
291
292 return result;
293 }
294
295 //--------------------------------------------------------------------------
296 /**
297 __newindex metamethod for classes.
298
299 This supports writable variables and properties on class objects. The
300 corresponding object is passed in the first parameter to the set function.
301 */
newindexMetaMethod(lua_State * L)302 static int newindexMetaMethod (lua_State* L)
303 {
304 int result = 0;
305
306 lua_getmetatable (L, 1);
307
308 for (;;)
309 {
310 // Check __propset
311 rawgetfield (L, -1, "__propset");
312 if (!lua_isnil (L, -1))
313 {
314 lua_pushvalue (L, 2);
315 lua_rawget (L, -2);
316 if (!lua_isnil (L, -1))
317 {
318 // found it, call the setFunction.
319 assert (lua_isfunction (L, -1));
320 lua_pushvalue (L, 1);
321 lua_pushvalue (L, 3);
322 lua_call (L, 2, 0);
323 result = 0;
324 break;
325 }
326 lua_pop (L, 1);
327 }
328 lua_pop (L, 1);
329
330 // Repeat the lookup in the __parent metafield.
331 rawgetfield (L, -1, "__parent");
332 if (lua_isnil (L, -1))
333 {
334 // Either the property or __parent must exist.
335 result = luaL_error (L,
336 "no member named '%s'", lua_tostring (L, 2));
337 }
338 lua_remove (L, -2);
339 }
340
341 return result;
342 }
343
344 //--------------------------------------------------------------------------
345 /**
346 Create the const table.
347 */
createConstTable(char const * name)348 void createConstTable (char const* name)
349 {
350 lua_newtable (L);
351 lua_pushvalue (L, -1);
352 lua_setmetatable (L, -2);
353 lua_pushboolean (L, 1);
354 lua_rawsetp (L, -2, getIdentityKey ());
355 lua_pushstring (L, (std::string ("const ") + name).c_str ());
356 rawsetfield (L, -2, "__type");
357 lua_pushcfunction (L, &indexMetaMethod);
358 rawsetfield (L, -2, "__index");
359 lua_pushcfunction (L, &newindexMetaMethod);
360 rawsetfield (L, -2, "__newindex");
361 lua_newtable (L);
362 rawsetfield (L, -2, "__propget");
363
364 if (Security::hideMetatables ())
365 {
366 lua_pushboolean (L, false);
367 rawsetfield (L, -2, "__metatable");
368 }
369 }
370
371 //--------------------------------------------------------------------------
372 /**
373 Create the class table.
374
375 The Lua stack should have the const table on top.
376 */
createClassTable(char const * name)377 void createClassTable (char const* name)
378 {
379 lua_newtable (L);
380 lua_pushvalue (L, -1);
381 lua_setmetatable (L, -2);
382 lua_pushboolean (L, 1);
383 lua_rawsetp (L, -2, getIdentityKey ());
384 lua_pushstring (L, name);
385 rawsetfield (L, -2, "__type");
386 lua_pushcfunction (L, &indexMetaMethod);
387 rawsetfield (L, -2, "__index");
388 lua_pushcfunction (L, &newindexMetaMethod);
389 rawsetfield (L, -2, "__newindex");
390 lua_newtable (L);
391 rawsetfield (L, -2, "__propget");
392 lua_newtable (L);
393 rawsetfield (L, -2, "__propset");
394
395 lua_pushvalue (L, -2);
396 rawsetfield (L, -2, "__const"); // point to const table
397
398 lua_pushvalue (L, -1);
399 rawsetfield (L, -3, "__class"); // point const table to class table
400
401 if (Security::hideMetatables ())
402 {
403 lua_pushboolean (L, false);
404 rawsetfield (L, -2, "__metatable");
405 }
406 }
407
408 //--------------------------------------------------------------------------
409 /**
410 Create the static table.
411
412 The Lua stack should have:
413 -1 class table
414 -2 const table
415 -3 enclosing namespace
416 */
createStaticTable(char const * name)417 void createStaticTable (char const* name)
418 {
419 lua_newtable (L);
420 lua_newtable (L);
421 lua_pushvalue (L, -1);
422 lua_setmetatable (L, -3);
423 lua_insert (L, -2);
424 rawsetfield (L, -5, name);
425
426 #if 0
427 lua_pushlightuserdata (L, this);
428 lua_pushcclosure (L, &tostringMetaMethod, 1);
429 rawsetfield (L, -2, "__tostring");
430 #endif
431 lua_pushcfunction (L, &CFunc::indexMetaMethod);
432 rawsetfield (L, -2, "__index");
433 lua_pushcfunction (L, &CFunc::newindexMetaMethod);
434 rawsetfield (L, -2, "__newindex");
435 lua_newtable (L);
436 rawsetfield (L, -2, "__propget");
437 lua_newtable (L);
438 rawsetfield (L, -2, "__propset");
439
440 lua_pushvalue (L, -2);
441 rawsetfield (L, -2, "__class"); // point to class table
442
443 if (Security::hideMetatables ())
444 {
445 lua_pushboolean (L, false);
446 rawsetfield (L, -2, "__metatable");
447 }
448 }
449
450 //==========================================================================
451 /**
452 lua_CFunction to construct a class object wrapped in a container.
453 */
454 template <class Params, class C>
ctorContainerProxy(lua_State * L)455 static int ctorContainerProxy (lua_State* L)
456 {
457 typedef typename ContainerTraits <C>::Type T;
458 ArgList <Params, 2> args (L);
459 T* const p = Constructor <T, Params>::call (args);
460 UserdataSharedHelper <C, false>::push (L, p);
461 return 1;
462 }
463
464 //--------------------------------------------------------------------------
465 /**
466 lua_CFunction to construct a class object in-place in the userdata.
467 */
468 template <class Params, class T>
ctorPlacementProxy(lua_State * L)469 static int ctorPlacementProxy (lua_State* L)
470 {
471 ArgList <Params, 2> args (L);
472 Constructor <T, Params>::call (UserdataValue <T>::place (L), args);
473 return 1;
474 }
475
476 template <class Params, class T, class C>
ctorPtrPlacementProxy(lua_State * L)477 static int ctorPtrPlacementProxy (lua_State* L)
478 {
479 ArgList <Params, 2> args (L);
480 T newobject (Constructor <C, Params>::call (args));
481 Stack<T>::push (L, newobject);
482 return 1;
483 }
484
485 template <class T>
ctorNilPtrPlacementProxy(lua_State * L)486 static int ctorNilPtrPlacementProxy (lua_State* L)
487 {
488 const T* newobject = new T ();
489 Stack<T>::push (L, *newobject);
490 return 1;
491 }
492
493 //--------------------------------------------------------------------------
494 /**
495 Pop the Lua stack.
496 */
pop(int n)497 void pop (int n) const
498 {
499 if (m_stackSize >= n && lua_gettop (L) >= n)
500 {
501 lua_pop (L, n);
502 m_stackSize -= n;
503 }
504 else
505 {
506 throw std::logic_error ("invalid stack");
507 }
508 }
509
510 public:
511 //--------------------------------------------------------------------------
ClassBase(lua_State * L_)512 explicit ClassBase (lua_State* L_)
513 : L (L_)
514 , m_stackSize (0)
515 {
516 }
517
518 //--------------------------------------------------------------------------
519 /**
520 Copy Constructor.
521 */
ClassBase(ClassBase const & other)522 ClassBase (ClassBase const& other)
523 : L (other.L)
524 , m_stackSize (0)
525 #ifdef LUABINDINGDOC
526 , _name (other._name)
527 , _parent (other._parent)
528 #endif
529 {
530 m_stackSize = other.m_stackSize;
531 other.m_stackSize = 0;
532 }
533
~ClassBase()534 ~ClassBase ()
535 {
536 pop (m_stackSize);
537 }
538 };
539
540 //============================================================================
541 //
542 // Class
543 //
544 //============================================================================
545 /**
546 Provides a class registration in a lua_State.
547
548 After contstruction the Lua stack holds these objects:
549 -1 static table
550 -2 class table
551 -3 const table
552 -4 (enclosing namespace)
553 */
554 template <class T>
555 class Class : virtual public ClassBase
556 {
557 public:
558 //==========================================================================
559 /**
560 Register a new class or add to an existing class registration.
561 */
Class(char const * name,Namespace const * parent)562 Class (char const* name, Namespace const* parent) : ClassBase (parent->L)
563 {
564 #ifdef LUABINDINGDOC
565 _parent = parent;
566 _name = parent->_name + name + ":";
567 #endif
568 PRINTDOC ("[C] Class", parent->_name << name, std::string(), type_name <T>())
569 m_stackSize = parent->m_stackSize + 3;
570 parent->m_stackSize = 0;
571
572 assert (lua_istable (L, -1));
573 rawgetfield (L, -1, name);
574
575 if (lua_isnil (L, -1))
576 {
577 lua_pop (L, 1);
578
579 createConstTable (name);
580 lua_pushcfunction (L, &CFunc::gcMetaMethod <T>);
581 rawsetfield (L, -2, "__gc");
582 lua_pushcclosure (L, &CFunc::ClassEqualCheck <T>::f, 0);
583 rawsetfield (L, -2, "__eq");
584
585 createClassTable (name);
586 lua_pushcfunction (L, &CFunc::gcMetaMethod <T>);
587 rawsetfield (L, -2, "__gc");
588 lua_pushcclosure (L, &CFunc::ClassEqualCheck <T>::f, 0);
589 rawsetfield (L, -2, "__eq");
590
591 createStaticTable (name);
592
593 // Map T back to its tables.
594 lua_pushvalue (L, -1);
595 lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getStaticKey ());
596 lua_pushvalue (L, -2);
597 lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getClassKey ());
598 lua_pushvalue (L, -3);
599 lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getConstKey ());
600 }
601 else
602 {
603 lua_pop (L, 1);
604 lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getStaticKey ());
605 rawgetfield (L, -1, "__class");
606 rawgetfield (L, -1, "__const");
607
608 // Reverse the top 3 stack elements
609 lua_insert (L, -3);
610 lua_insert (L, -2);
611 }
612 }
613
614 //==========================================================================
615 /**
616 Derive a new class.
617 */
Class(char const * name,Namespace const * parent,void const * const staticKey)618 Class (char const* name, Namespace const* parent, void const* const staticKey)
619 : ClassBase (parent->L)
620 {
621 #ifdef LUABINDINGDOC
622 _parent = parent;
623 _name = parent->_name + name + ":";
624 #endif
625 m_stackSize = parent->m_stackSize + 3;
626 parent->m_stackSize = 0;
627
628 assert (lua_istable (L, -1));
629
630 createConstTable (name);
631 lua_pushcfunction (L, &CFunc::gcMetaMethod <T>);
632 rawsetfield (L, -2, "__gc");
633 lua_pushcclosure (L, &CFunc::ClassEqualCheck <T>::f, 0);
634 rawsetfield (L, -2, "__eq");
635
636 createClassTable (name);
637 lua_pushcfunction (L, &CFunc::gcMetaMethod <T>);
638 rawsetfield (L, -2, "__gc");
639 lua_pushcclosure (L, &CFunc::ClassEqualCheck <T>::f, 0);
640 rawsetfield (L, -2, "__eq");
641
642 createStaticTable (name);
643
644 lua_rawgetp (L, LUA_REGISTRYINDEX, staticKey);
645 assert (lua_istable (L, -1));
646 rawgetfield (L, -1, "__class");
647 assert (lua_istable (L, -1));
648 rawgetfield (L, -1, "__const");
649 assert (lua_istable (L, -1));
650
651 rawsetfield (L, -6, "__parent");
652 rawsetfield (L, -4, "__parent");
653 rawsetfield (L, -2, "__parent");
654
655 lua_pushvalue (L, -1);
656 lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getStaticKey ());
657 lua_pushvalue (L, -2);
658 lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getClassKey ());
659 lua_pushvalue (L, -3);
660 lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getConstKey ());
661 }
662
663 //--------------------------------------------------------------------------
664 /**
665 Continue registration in the enclosing namespace.
666 */
endClass()667 Namespace endClass ()
668 {
669 return Namespace (this);
670 }
671
672 //--------------------------------------------------------------------------
673 /**
674 Add or replace a static data member.
675 */
676 template <class U>
677 Class <T>& addStaticData (char const* name, U* pu, bool isWritable = true)
678 {
679 DATADOC ("Static Data Member", name, pu)
680 assert (lua_istable (L, -1));
681
682 rawgetfield (L, -1, "__propget");
683 assert (lua_istable (L, -1));
684 lua_pushlightuserdata (L, pu);
685 lua_pushcclosure (L, &CFunc::getVariable <U>, 1);
686 rawsetfield (L, -2, name);
687 lua_pop (L, 1);
688
689 rawgetfield (L, -1, "__propset");
690 assert (lua_istable (L, -1));
691 if (isWritable)
692 {
693 lua_pushlightuserdata (L, pu);
694 lua_pushcclosure (L, &CFunc::setVariable <U>, 1);
695 }
696 else
697 {
698 lua_pushstring (L, name);
699 lua_pushcclosure (L, &CFunc::readOnlyError, 1);
700 }
701 rawsetfield (L, -2, name);
702 lua_pop (L, 1);
703
704 return *this;
705 }
706
707 //--------------------------------------------------------------------------
708 #if 0 // unused
709 /**
710 Add or replace a static property member.
711
712 If the set function is null, the property is read-only.
713 */
714 template <class U>
715 Class <T>& addStaticProperty (char const* name, U (*get)(), void (*set)(U) = 0)
716 {
717 typedef U (*get_t)();
718 typedef void (*set_t)(U);
719
720 assert (lua_istable (L, -1));
721
722 rawgetfield (L, -1, "__propget");
723 assert (lua_istable (L, -1));
724 new (lua_newuserdata (L, sizeof (get))) get_t (get);
725 lua_pushcclosure (L, &CFunc::Call <U (*) (void)>::f, 1);
726 rawsetfield (L, -2, name);
727 lua_pop (L, 1);
728
729 rawgetfield (L, -1, "__propset");
730 assert (lua_istable (L, -1));
731 if (set != 0)
732 {
733 new (lua_newuserdata (L, sizeof (set))) set_t (set);
734 lua_pushcclosure (L, &CFunc::Call <void (*) (U)>::f, 1);
735 }
736 else
737 {
738 lua_pushstring (L, name);
739 lua_pushcclosure (L, &CFunc::readOnlyError, 1);
740 }
741 rawsetfield (L, -2, name);
742 lua_pop (L, 1);
743
744 return *this;
745 }
746 #endif
747
748 //--------------------------------------------------------------------------
749 /**
750 Add or replace a static member function.
751 */
752 template <class FP>
addStaticFunction(char const * name,FP const fp)753 Class <T>& addStaticFunction (char const* name, FP const fp)
754 {
755 FUNDOC ("Static Member Function", name, FP)
756 new (lua_newuserdata (L, sizeof (fp))) FP (fp);
757 lua_pushcclosure (L, &CFunc::Call <FP>::f, 1);
758 rawsetfield (L, -2, name);
759
760 return *this;
761 }
762
763 //--------------------------------------------------------------------------
764 /**
765 Add or replace a lua_CFunction.
766 */
addStaticCFunction(char const * name,int (* const fp)(lua_State *))767 Class <T>& addStaticCFunction (char const* name, int (*const fp)(lua_State*))
768 {
769 DATADOC ("Static C Function", name, fp)
770 lua_pushcfunction (L, fp);
771 rawsetfield (L, -2, name);
772 return *this;
773 }
774
775 //--------------------------------------------------------------------------
776 /**
777 Add or replace a data member.
778 */
779 template <class U>
780 Class <T>& addData (char const* name, const U T::* mp, bool isWritable = true)
781 {
782 DATADOC ("Data Member", name, mp)
783 typedef const U T::*mp_t;
784
785 // Add to __propget in class and const tables.
786 {
787 rawgetfield (L, -2, "__propget");
788 rawgetfield (L, -4, "__propget");
789 new (lua_newuserdata (L, sizeof (mp_t))) mp_t (mp);
790 lua_pushcclosure (L, &CFunc::getProperty <T,U>, 1);
791 lua_pushvalue (L, -1);
792 rawsetfield (L, -4, name);
793 rawsetfield (L, -2, name);
794 lua_pop (L, 2);
795 }
796
797 if (isWritable)
798 {
799 // Add to __propset in class table.
800 rawgetfield (L, -2, "__propset");
801 assert (lua_istable (L, -1));
802 new (lua_newuserdata (L, sizeof (mp_t))) mp_t (mp);
803 lua_pushcclosure (L, &CFunc::setProperty <T,U>, 1);
804 rawsetfield (L, -2, name);
805 lua_pop (L, 1);
806 }
807
808 return *this;
809 }
810
811 //--------------------------------------------------------------------------
812 /**
813 Add or replace a property member.
814 */
815 template <class TG, class TS>
addProperty(char const * name,TG (T::* get)()const,bool (T::* set)(TS))816 Class <T>& addProperty (char const* name, TG (T::* get) () const, bool (T::* set) (TS))
817 {
818 DATADOC ("Property", name, get)
819 // Add to __propget in class and const tables.
820 {
821 rawgetfield (L, -2, "__propget");
822 rawgetfield (L, -4, "__propget");
823 typedef TG (T::*get_t) () const;
824 new (lua_newuserdata (L, sizeof (get_t))) get_t (get);
825 lua_pushcclosure (L, &CFunc::CallConstMember <get_t>::f, 1);
826 lua_pushvalue (L, -1);
827 rawsetfield (L, -4, name);
828 rawsetfield (L, -2, name);
829 lua_pop (L, 2);
830 }
831
832 {
833 // Add to __propset in class table.
834 rawgetfield (L, -2, "__propset");
835 assert (lua_istable (L, -1));
836 typedef bool (T::* set_t) (TS);
837 new (lua_newuserdata (L, sizeof (set_t))) set_t (set);
838 lua_pushcclosure (L, &CFunc::CallMember <set_t>::f, 1);
839 rawsetfield (L, -2, name);
840 lua_pop (L, 1);
841 }
842
843 return *this;
844 }
845
846 #if 0 // unused
847 // read-only
848 template <class TG>
849 Class <T>& addProperty (char const* name, TG (T::* get) () const)
850 {
851 // Add to __propget in class and const tables.
852 rawgetfield (L, -2, "__propget");
853 rawgetfield (L, -4, "__propget");
854 typedef TG (T::*get_t) () const;
855 new (lua_newuserdata (L, sizeof (get_t))) get_t (get);
856 lua_pushcclosure (L, &CFunc::CallConstMember <get_t>::f, 1);
857 lua_pushvalue (L, -1);
858 rawsetfield (L, -4, name);
859 rawsetfield (L, -2, name);
860 lua_pop (L, 2);
861
862 return *this;
863 }
864 #endif
865
866 //--------------------------------------------------------------------------
867 /**
868 Add or replace a property member, by proxy.
869
870 When a class is closed for modification and does not provide (or cannot
871 provide) the function signatures necessary to implement get or set for
872 a property, this will allow non-member functions act as proxies.
873
874 Both the get and the set functions require a T const* and T* in the first
875 argument respectively.
876 */
877 template <class TG, class TS>
addProperty(char const * name,TG (* get)(T const *),bool (* set)(T *,TS))878 Class <T>& addProperty (char const* name, TG (*get) (T const*), bool (*set) (T*, TS))
879 {
880 // Add to __propget in class and const tables.
881 {
882 rawgetfield (L, -2, "__propget");
883 rawgetfield (L, -4, "__propget");
884 typedef TG (*get_t) (T const*);
885 new (lua_newuserdata (L, sizeof (get_t))) get_t (get);
886 lua_pushcclosure (L, &CFunc::Call <get_t>::f, 1);
887 lua_pushvalue (L, -1);
888 rawsetfield (L, -4, name);
889 rawsetfield (L, -2, name);
890 lua_pop (L, 2);
891 }
892
893 if (set != 0)
894 {
895 // Add to __propset in class table.
896 rawgetfield (L, -2, "__propset");
897 assert (lua_istable (L, -1));
898 typedef void (*set_t) (T*, TS);
899 new (lua_newuserdata (L, sizeof (set_t))) set_t (set);
900 lua_pushcclosure (L, &CFunc::Call <set_t>::f, 1);
901 rawsetfield (L, -2, name);
902 lua_pop (L, 1);
903 }
904
905 return *this;
906 }
907
908 #if 0 // unused
909 // read-only
910 template <class TG, class TS>
911 Class <T>& addProperty (char const* name, TG (*get) (T const*))
912 {
913 // Add to __propget in class and const tables.
914 rawgetfield (L, -2, "__propget");
915 rawgetfield (L, -4, "__propget");
916 typedef TG (*get_t) (T const*);
917 new (lua_newuserdata (L, sizeof (get_t))) get_t (get);
918 lua_pushcclosure (L, &CFunc::Call <get_t>::f, 1);
919 lua_pushvalue (L, -1);
920 rawsetfield (L, -4, name);
921 rawsetfield (L, -2, name);
922 lua_pop (L, 2);
923
924 return *this;
925 }
926 #endif
927 //--------------------------------------------------------------------------
928 /**
929 Add or replace a member function.
930 */
931 template <class MemFn>
addFunction(char const * name,MemFn mf)932 Class <T>& addFunction (char const* name, MemFn mf)
933 {
934 FUNDOC("Member Function", name, MemFn)
935 CFunc::CallMemberFunctionHelper <MemFn, FuncTraits <MemFn>::isConstMemberFunction>::add (L, name, mf);
936 return *this;
937 }
938
939 template <class MemFn>
addPtrFunction(char const * name,MemFn mf)940 Class <T>& addPtrFunction (char const* name, MemFn mf)
941 {
942 FUNDOC("Member Pointer Function", name, MemFn)
943 CFunc::CallMemberPtrFunctionHelper <MemFn>::add (L, name, mf);
944 return *this;
945 }
946
947 template <class MemFn>
addWPtrFunction(char const * name,MemFn mf)948 Class <T>& addWPtrFunction (char const* name, MemFn mf)
949 {
950 FUNDOC("Member Weak Pointer Function", name, MemFn)
951 CFunc::CallMemberWPtrFunctionHelper <MemFn>::add (L, name, mf);
952 return *this;
953 }
954
955 template <class MemFn>
addRefFunction(char const * name,MemFn mf)956 Class <T>& addRefFunction (char const* name, MemFn mf)
957 {
958 FUNDOC("Member Function RefReturn", name, MemFn)
959 CFunc::CallMemberRefFunctionHelper <MemFn, FuncTraits <MemFn>::isConstMemberFunction>::add (L, name, mf);
960 return *this;
961 }
962
963
964 //--------------------------------------------------------------------------
965 /**
966 Add or replace a member lua_CFunction.
967 */
addCFunction(char const * name,int (T::* mfp)(lua_State *))968 Class <T>& addCFunction (char const* name, int (T::*mfp)(lua_State*))
969 {
970 DATADOC ("C Function", name, mfp)
971 typedef int (T::*MFP)(lua_State*);
972 assert (lua_istable (L, -1));
973 new (lua_newuserdata (L, sizeof (mfp))) MFP (mfp);
974 lua_pushcclosure (L, &CFunc::CallMemberCFunction <T>::f, 1);
975 rawsetfield (L, -3, name); // class table
976
977 return *this;
978 }
979
980 // custom callback - extend existing classes
981 // with non-class member functions (e.g STL iterator)
addExtCFunction(char const * name,int (* const fp)(lua_State *))982 Class <T>& addExtCFunction (char const* name, int (*const fp)(lua_State*))
983 {
984 DATADOC ("Ext C Function", name, fp)
985 assert (lua_istable (L, -1));
986 lua_pushcclosure (L, fp, 0);
987 lua_pushvalue (L, -1);
988 rawsetfield (L, -5, name); // const table
989 rawsetfield (L, -3, name); // class table
990 return *this;
991 }
992
993 //--------------------------------------------------------------------------
994 /**
995 Add or replace a const member lua_CFunction.
996 */
addCFunction(char const * name,int (T::* mfp)(lua_State *)const)997 Class <T>& addCFunction (char const* name, int (T::*mfp)(lua_State*) const)
998 {
999 DATADOC ("Const C Member Function", name, mfp)
1000 typedef int (T::*MFP)(lua_State*) const;
1001 assert (lua_istable (L, -1));
1002 new (lua_newuserdata (L, sizeof (mfp))) MFP (mfp);
1003 lua_pushcclosure (L, &CFunc::CallConstMemberCFunction <T>::f, 1);
1004 lua_pushvalue (L, -1);
1005 rawsetfield (L, -5, name); // const table
1006 rawsetfield (L, -3, name); // class table
1007
1008 return *this;
1009 }
1010
1011 /**
1012 Add or replace a static const data
1013 */
1014 template <typename U>
addConst(char const * name,const U val)1015 Class <T>& addConst (char const* name, const U val)
1016 {
1017 DATADOC ("Constant/Enum Member", name, val)
1018 assert (lua_istable (L, -1));
1019
1020 rawgetfield (L, -1, "__propget"); // static
1021 new (lua_newuserdata (L, sizeof (val))) U (val);
1022 lua_pushcclosure (L, &CFunc::getConst <U>, 1);
1023 rawsetfield (L, -2, name);
1024 lua_pop (L, 1);
1025
1026 rawgetfield (L, -1, "__propset"); // static
1027 lua_pushstring (L, name);
1028 lua_pushcclosure (L, &CFunc::readOnlyError, 1);
1029 rawsetfield (L, -2, name);
1030 lua_pop (L, 1);
1031 return *this;
1032 }
1033
1034 //--------------------------------------------------------------------------
1035 /**
1036 Add or replace a primary Constructor.
1037
1038 The primary Constructor is invoked when calling the class type table
1039 like a function.
1040
1041 The template parameter should be a function pointer type that matches
1042 the desired Constructor (since you can't take the address of a Constructor
1043 and pass it as an argument).
1044 */
1045 template <class MemFn, class C>
addConstructor()1046 Class <T>& addConstructor ()
1047 {
1048 FUNDOC("Constructor", "", MemFn)
1049 lua_pushcclosure (L,
1050 &ctorContainerProxy <typename FuncTraits <MemFn>::Params, C>, 0);
1051 rawsetfield(L, -2, "__call");
1052
1053 return *this;
1054 }
1055
1056 template <class MemFn>
addConstructor()1057 Class <T>& addConstructor ()
1058 {
1059 FUNDOC("Constructor", "", MemFn)
1060 lua_pushcclosure (L,
1061 &ctorPlacementProxy <typename FuncTraits <MemFn>::Params, T>, 0);
1062 rawsetfield(L, -2, "__call");
1063
1064 return *this;
1065 }
1066
1067 template <class MemFn, class PT>
addPtrConstructor()1068 Class <T>& addPtrConstructor ()
1069 {
1070 FUNDOC("Constructor", "", MemFn)
1071 lua_pushcclosure (L,
1072 &ctorPtrPlacementProxy <typename FuncTraits <MemFn>::Params, T, PT>, 0);
1073 rawsetfield(L, -2, "__call");
1074
1075 return *this;
1076 }
1077
addVoidConstructor()1078 Class <T>& addVoidConstructor ()
1079 {
1080 return addConstructor <void (*) ()> ();
1081 }
1082
1083 template <class PT>
addVoidPtrConstructor()1084 Class <T>& addVoidPtrConstructor ()
1085 {
1086 return addPtrConstructor <void (*) (), PT> ();
1087 }
1088
addEqualCheck()1089 Class <T>& addEqualCheck ()
1090 {
1091 assert (lua_istable (L, -1));
1092 lua_pushcclosure (L, &CFunc::ClassEqualCheck <T>::f, 0);
1093 rawsetfield (L, -3, "sameinstance");
1094 return *this;
1095 }
1096
1097 template <class U>
addCast(char const * name)1098 Class <T>& addCast (char const* name)
1099 {
1100 PRINTDOC("Cast", _name << name,
1101 type_name< U >(),
1102 type_name< U >() << " (" << type_name< T >() << "::*)()")
1103
1104 assert (lua_istable (L, -1));
1105 lua_pushcclosure (L, &CFunc::CastClass <T, U>::f, 0);
1106 rawsetfield (L, -3, name); // class table
1107
1108 lua_pushcclosure (L, &CFunc::CastConstClass <T, U>::f, 0);
1109 rawsetfield (L, -4, name); // const table
1110 return *this;
1111 }
1112
1113 };
1114
1115 /** C Array to/from table */
1116 template <typename T>
1117 class Array : virtual public ClassBase
1118 {
1119 public:
Array(char const * name,Namespace const * parent)1120 Array (char const* name, Namespace const* parent) : ClassBase (parent->L)
1121 {
1122 #ifdef LUABINDINGDOC
1123 _parent = parent;
1124 _name = parent->_name + name + ":";
1125 #endif
1126 PRINTDOC ("[C] Array", parent->_name << name,
1127 std::string(), type_name <T>() + "*")
1128 PRINTDOC ("Ext C Function", _name << "array",
1129 std::string(""), "int (*)(lua_State*)")
1130 PRINTDOC ("Ext C Function", _name << "get_table",
1131 std::string(""), "int (*)(lua_State*)")
1132 PRINTDOC ("Ext C Function", _name << "set_table",
1133 std::string(""), "int (*)(lua_State*)")
1134 PRINTDOC("Member Function", _name << "offset",
1135 std::string(type_name <T>() + "*"), std::string(type_name <T>() + "* (*)(unsigned int)"))
1136
1137 m_stackSize = parent->m_stackSize + 3;
1138 parent->m_stackSize = 0;
1139
1140 #if 0 // don't allow to duplicates handlers for same array-type
1141 assert (lua_istable (L, -1));
1142 lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getClassKey ());
1143 if (lua_istable (L, -1)) {
1144 lua_pushnil (L);
1145 lua_pushnil (L);
1146 return;
1147 }
1148 lua_pop (L, 1);
1149 #endif
1150
1151 assert (lua_istable (L, -1));
1152 rawgetfield (L, -1, name);
1153
1154 if (lua_isnil (L, -1))
1155 {
1156 lua_pop (L, 1);
1157
1158 // register array access in global namespace
1159 luaL_newmetatable (L, typeid(T).name());
1160 lua_pushcclosure (L, CFunc::array_index<T>, 0);
1161 lua_setfield(L, -2, "__index");
1162 lua_pushcclosure (L, CFunc::array_newindex<T>, 0);
1163 lua_setfield(L, -2, "__newindex");
1164 if (Security::hideMetatables ())
1165 {
1166 lua_pushboolean (L, false);
1167 rawsetfield (L, -2, "__metatable");
1168 }
1169 lua_pop (L, 1);
1170
1171
1172 createConstTable (name);
1173 lua_pushcfunction (L, &CFunc::gcMetaMethod <T>);
1174 rawsetfield (L, -2, "__gc");
1175 lua_pushcclosure (L, &CFunc::ClassEqualCheck <T>::f, 0);
1176 rawsetfield (L, -2, "__eq");
1177
1178 createClassTable (name);
1179 lua_pushcfunction (L, &CFunc::gcMetaMethod <T>);
1180 rawsetfield (L, -2, "__gc");
1181 lua_pushcclosure (L, &CFunc::ClassEqualCheck <T>::f, 0);
1182 rawsetfield (L, -2, "__eq");
1183
1184 createStaticTable (name);
1185
1186 // Map T back to its tables.
1187 lua_pushvalue (L, -1);
1188 lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getStaticKey ());
1189 lua_pushvalue (L, -2);
1190 lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getClassKey ());
1191 lua_pushvalue (L, -3);
1192 lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getConstKey ());
1193
1194 assert (lua_istable (L, -1));
1195 lua_pushcclosure (L, &CFunc::getArray <T>, 0);
1196 rawsetfield (L, -3, "array"); // class table
1197
1198 lua_pushcclosure (L, &CFunc::getTable <T>, 0);
1199 rawsetfield (L, -3, "get_table"); // class table
1200
1201 lua_pushcclosure (L, &CFunc::setTable <T>, 0);
1202 rawsetfield (L, -3, "set_table"); // class table
1203
1204 lua_pushcclosure (L, &CFunc::ClassEqualCheck <T>::f, 0);
1205 rawsetfield (L, -3, "sameinstance");
1206
1207 lua_pushcclosure (L, &CFunc::offsetArray <T>, 0);
1208 rawsetfield (L, -3, "offset"); // class table
1209
1210 }
1211 else
1212 {
1213 lua_pushnil (L);
1214 lua_pushnil (L);
1215 }
1216 }
1217
endArray()1218 Namespace endArray ()
1219 {
1220 return Namespace (this);
1221 }
1222 };
1223
1224 /** Boost Weak & Shared Pointer Class Wrapper */
1225 template <class T>
1226 class WSPtrClass : virtual public ClassBase
1227 {
1228 public:
WSPtrClass(char const * name,Namespace const * parent)1229 WSPtrClass (char const* name, Namespace const* parent)
1230 : ClassBase (parent->L)
1231 , shared (name, parent)
1232 , weak (name, parent)
1233 {
1234 #ifdef LUABINDINGDOC
1235 _parent = parent;
1236 _name = parent->_name + name + ":";
1237 #endif
1238 PRINTDOC ("[C] Weak/Shared Pointer Class",
1239 parent->_name + name,
1240 std::string(), type_name <T>())
1241 m_stackSize = shared.m_stackSize;
1242 parent->m_stackSize = weak.m_stackSize = shared.m_stackSize = 0;
1243 lua_pop (L, 3);
1244 }
1245
WSPtrClass(char const * name,Namespace const * parent,void const * const sharedkey,void const * const weakkey)1246 WSPtrClass (char const* name, Namespace const* parent, void const* const sharedkey, void const* const weakkey)
1247 : ClassBase (parent->L)
1248 , shared (name, parent, sharedkey)
1249 , weak (name, parent, weakkey)
1250 {
1251 #ifdef LUABINDINGDOC
1252 _parent = parent;
1253 _name = parent->_name + name + ":";
1254 #endif
1255 m_stackSize = shared.m_stackSize;
1256 parent->m_stackSize = weak.m_stackSize = shared.m_stackSize = 0;
1257 lua_pop (L, 3);
1258 }
1259
1260 template <class MemFn>
addFunction(char const * name,MemFn mf)1261 WSPtrClass <T>& addFunction (char const* name, MemFn mf)
1262 {
1263 FUNDOC ("Weak/Shared Pointer Function", name, MemFn)
1264 set_shared_class ();
1265 CFunc::CallMemberPtrFunctionHelper <MemFn>::add (L, name, mf);
1266
1267 set_weak_class ();
1268 CFunc::CallMemberWPtrFunctionHelper <MemFn>::add (L, name, mf);
1269 return *this;
1270 }
1271
1272 template <class MemFn>
addRefFunction(char const * name,MemFn mf)1273 WSPtrClass <T>& addRefFunction (char const* name, MemFn mf)
1274 {
1275 FUNDOC ("Weak/Shared Pointer Function RefReturn", name, MemFn)
1276 set_shared_class ();
1277 CFunc::CallMemberRefPtrFunctionHelper <MemFn>::add (L, name, mf);
1278
1279 set_weak_class ();
1280 CFunc::CallMemberRefWPtrFunctionHelper <MemFn>::add (L, name, mf);
1281 return *this;
1282 }
1283
1284 template <class MemFn>
addConstructor()1285 WSPtrClass <T>& addConstructor ()
1286 {
1287 FUNDOC ("Weak/Shared Pointer Constructor", "", MemFn)
1288 set_shared_class ();
1289 lua_pushcclosure (L,
1290 &shared. template ctorPtrPlacementProxy <typename FuncTraits <MemFn>::Params, boost::shared_ptr<T>, T >, 0);
1291 rawsetfield(L, -2, "__call");
1292
1293 set_weak_class ();
1294 // NOTE: this constructs an empty weak-ptr,
1295 // ideally we'd construct a weak-ptr from a referenced shared-ptr
1296 lua_pushcclosure (L,
1297 &weak. template ctorPlacementProxy <typename FuncTraits <MemFn>::Params, boost::weak_ptr<T> >, 0);
1298 rawsetfield(L, -2, "__call");
1299 return *this;
1300 }
1301
addVoidConstructor()1302 WSPtrClass <T>& addVoidConstructor ()
1303 {
1304 return addConstructor <void (*) ()> ();
1305 }
1306
1307 template <class FP>
addStaticFunction(char const * name,FP const fp)1308 WSPtrClass <T>& addStaticFunction (char const* name, FP const fp)
1309 {
1310 FUNDOC ("Static Member Function", name, FP)
1311 set_shared_class ();
1312 new (lua_newuserdata (L, sizeof (fp))) FP (fp);
1313 lua_pushcclosure (L, &CFunc::Call <FP>::f, 1);
1314 rawsetfield (L, -2, name);
1315
1316 set_weak_class ();
1317 new (lua_newuserdata (L, sizeof (fp))) FP (fp);
1318 lua_pushcclosure (L, &CFunc::Call <FP>::f, 1);
1319 rawsetfield (L, -2, name);
1320 return *this;
1321 }
1322
addNilPtrConstructor()1323 WSPtrClass <T>& addNilPtrConstructor ()
1324 {
1325 FUNDOC ("Weak/Shared Pointer NIL Constructor", "", void (*) ())
1326 set_shared_class ();
1327 lua_pushcclosure (L,
1328 &shared. template ctorNilPtrPlacementProxy <boost::shared_ptr<T> >, 0);
1329 rawsetfield(L, -2, "__call");
1330
1331 set_weak_class ();
1332 // NOTE: this constructs an empty weak-ptr,
1333 // ideally we'd construct a weak-ptr from a referenced shared-ptr
1334 lua_pushcclosure (L,
1335 &weak. template ctorNilPtrPlacementProxy <boost::weak_ptr<T> >, 0);
1336 rawsetfield(L, -2, "__call");
1337
1338 return *this;
1339 }
1340
addExtCFunction(char const * name,int (* const fp)(lua_State *))1341 WSPtrClass <T>& addExtCFunction (char const* name, int (*const fp)(lua_State*))
1342 {
1343 DATADOC ("Weak/Shared Ext C Function", name, fp)
1344 set_shared_class ();
1345 assert (lua_istable (L, -1));
1346 lua_pushcclosure (L, fp, 0);
1347 lua_pushvalue (L, -1);
1348 rawsetfield (L, -5, name); // const table
1349 rawsetfield (L, -3, name); // class table
1350
1351 set_weak_class ();
1352 assert (lua_istable (L, -1));
1353 lua_pushcclosure (L, fp, 0);
1354 lua_pushvalue (L, -1);
1355 rawsetfield (L, -5, name); // const table
1356 rawsetfield (L, -3, name); // class table
1357
1358 return *this;
1359 }
1360
1361 template <class U>
addCast(char const * name)1362 WSPtrClass <T>& addCast (char const* name)
1363 {
1364 PRINTDOC("Weak/Shared Pointer Cast", _name << name,
1365 type_name< U >(),
1366 type_name< U >() << " (" << type_name< T >() << "::*)()")
1367
1368 // TODO weak ptr
1369 set_shared_class ();
1370 assert (lua_istable (L, -1));
1371 lua_pushcclosure (L, &CFunc::CastMemberPtr <T, U>::f, 0);
1372 rawsetfield (L, -3, name); // class table
1373 return *this;
1374 }
1375
addNullCheck()1376 WSPtrClass <T>& addNullCheck ()
1377 {
1378 PRINTDOC("Weak/Shared Null Check", _name << "isnil", std::string("bool"), std::string("void (*)()"))
1379 set_shared_class ();
1380 assert (lua_istable (L, -1));
1381 lua_pushcclosure (L, &CFunc::PtrNullCheck <T>::f, 0);
1382 rawsetfield (L, -3, "isnil"); // class table
1383
1384 set_weak_class ();
1385 assert (lua_istable (L, -1));
1386 lua_pushcclosure (L, &CFunc::WPtrNullCheck <T>::f, 0);
1387 rawsetfield (L, -3, "isnil"); // class table
1388
1389 return *this;
1390 }
1391
addEqualCheck()1392 WSPtrClass <T>& addEqualCheck ()
1393 {
1394 set_shared_class ();
1395 assert (lua_istable (L, -1));
1396 lua_pushcclosure (L, &CFunc::PtrEqualCheck <T>::f, 0);
1397 rawsetfield (L, -3, "sameinstance"); // class table
1398
1399 set_weak_class ();
1400 assert (lua_istable (L, -1));
1401 lua_pushcclosure (L, &CFunc::WPtrEqualCheck <T>::f, 0);
1402 rawsetfield (L, -3, "sameinstance"); // class table
1403
1404 return *this;
1405 }
1406
1407 template <class U>
1408 WSPtrClass <T>& addData (char const* name, const U T::* mp, bool isWritable = true)
1409 {
1410 DATADOC ("Data Member", name, mp)
1411 typedef const U T::*mp_t;
1412
1413 set_weak_class ();
1414 assert (lua_istable (L, -1));
1415 // Add to __propget in class and const tables.
1416 {
1417 rawgetfield (L, -2, "__propget");
1418 rawgetfield (L, -4, "__propget");
1419 new (lua_newuserdata (L, sizeof (mp_t))) mp_t (mp);
1420 lua_pushcclosure (L, &CFunc::getWPtrProperty <T,U>, 1);
1421 lua_pushvalue (L, -1);
1422 rawsetfield (L, -4, name);
1423 rawsetfield (L, -2, name);
1424 lua_pop (L, 2);
1425 }
1426
1427 if (isWritable)
1428 {
1429 // Add to __propset in class table.
1430 rawgetfield (L, -2, "__propset");
1431 assert (lua_istable (L, -1));
1432 new (lua_newuserdata (L, sizeof (mp_t))) mp_t (mp);
1433 lua_pushcclosure (L, &CFunc::setWPtrProperty <T,U>, 1);
1434 rawsetfield (L, -2, name);
1435 lua_pop (L, 1);
1436 }
1437
1438 set_shared_class ();
1439 assert (lua_istable (L, -1));
1440 // Add to __propget in class and const tables.
1441 {
1442 rawgetfield (L, -2, "__propget");
1443 rawgetfield (L, -4, "__propget");
1444 new (lua_newuserdata (L, sizeof (mp_t))) mp_t (mp);
1445 lua_pushcclosure (L, &CFunc::getPtrProperty <T,U>, 1);
1446 lua_pushvalue (L, -1);
1447 rawsetfield (L, -4, name);
1448 rawsetfield (L, -2, name);
1449 lua_pop (L, 2);
1450 }
1451
1452 if (isWritable)
1453 {
1454 // Add to __propset in class table.
1455 rawgetfield (L, -2, "__propset");
1456 assert (lua_istable (L, -1));
1457 new (lua_newuserdata (L, sizeof (mp_t))) mp_t (mp);
1458 lua_pushcclosure (L, &CFunc::setPtrProperty <T,U>, 1);
1459 rawsetfield (L, -2, name);
1460 lua_pop (L, 1);
1461 }
1462
1463 return *this;
1464 }
1465
1466
endClass()1467 Namespace endClass ()
1468 {
1469 return Namespace (this);
1470 }
1471
1472 private:
set_weak_class()1473 void set_weak_class () {
1474 lua_pop (L, 3);
1475 lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <boost::weak_ptr<T> >::getStaticKey ());
1476 rawgetfield (L, -1, "__class");
1477 rawgetfield (L, -1, "__const");
1478 lua_insert (L, -3);
1479 lua_insert (L, -2);
1480 }
set_shared_class()1481 void set_shared_class () {
1482 lua_pop (L, 3);
1483 lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <boost::shared_ptr<T> >::getStaticKey ());
1484 rawgetfield (L, -1, "__class");
1485 rawgetfield (L, -1, "__const");
1486 lua_insert (L, -3);
1487 lua_insert (L, -2);
1488 }
1489 Class<boost::shared_ptr<T> > shared;
1490 Class<boost::weak_ptr<T> > weak;
1491 };
1492
1493
1494 private:
1495 //----------------------------------------------------------------------------
1496 /**
1497 Open the global namespace for registrations.
1498 */
Namespace(lua_State * L_)1499 explicit Namespace (lua_State* L_)
1500 : L (L_)
1501 , m_stackSize (0)
1502 #ifdef LUABINDINGDOC
1503 , _name ("")
1504 , _parent (0)
1505 #endif
1506 {
1507 lua_getglobal (L, "_G");
1508 ++m_stackSize;
1509 }
1510
1511 #ifdef LUABINDINGDOC
1512 std::string _name;
1513 Namespace const * _parent;
1514 #endif
1515
1516 //----------------------------------------------------------------------------
1517 /**
1518 Open a namespace for registrations.
1519
1520 The namespace is created if it doesn't already exist.
1521 The parent namespace is at the top of the Lua stack.
1522 */
Namespace(char const * name,Namespace const * parent)1523 Namespace (char const* name, Namespace const* parent)
1524 : L (parent->L)
1525 , m_stackSize (0)
1526 #ifdef LUABINDINGDOC
1527 , _name (parent->_name + name + ":")
1528 , _parent (parent)
1529 #endif
1530 {
1531 m_stackSize = parent->m_stackSize + 1;
1532 parent->m_stackSize = 0;
1533
1534 assert (lua_istable (L, -1));
1535 rawgetfield (L, -1, name);
1536 if (lua_isnil (L, -1))
1537 {
1538 lua_pop (L, 1);
1539
1540 lua_newtable (L);
1541 lua_pushvalue (L, -1);
1542 lua_setmetatable (L, -2);
1543 lua_pushcfunction (L, &CFunc::indexMetaMethod);
1544 rawsetfield (L, -2, "__index");
1545 lua_pushcfunction (L, &CFunc::newindexMetaMethod);
1546 rawsetfield (L, -2, "__newindex");
1547 lua_newtable (L);
1548 rawsetfield (L, -2, "__propget");
1549 lua_newtable (L);
1550 rawsetfield (L, -2, "__propset");
1551 lua_pushvalue (L, -1);
1552 rawsetfield (L, -3, name);
1553 #if 0
1554 lua_pushcfunction (L, &tostringMetaMethod);
1555 rawsetfield (L, -2, "__tostring");
1556 #endif
1557 if (Security::hideMetatables ())
1558 {
1559 lua_pushboolean (L, false);
1560 rawsetfield (L, -2, "__metatable");
1561 }
1562
1563 }
1564 }
1565
1566 //----------------------------------------------------------------------------
1567 /**
1568 Creates a continued registration from a child namespace.
1569 */
Namespace(Namespace const * child)1570 explicit Namespace (Namespace const* child)
1571 : L (child->L)
1572 , m_stackSize (0)
1573 #ifdef LUABINDINGDOC
1574 , _name (child->_parent ? child->_parent->_name : "")
1575 , _parent (child->_parent ? child->_parent->_parent : NULL)
1576 #endif
1577 {
1578 m_stackSize = child->m_stackSize - 1;
1579 child->m_stackSize = 1;
1580 child->pop (1);
1581
1582 // It is not necessary or valid to call
1583 // endNamespace() for the global namespace!
1584 //
1585 assert (m_stackSize != 0);
1586 }
1587
1588 //----------------------------------------------------------------------------
1589 /**
1590 Creates a continued registration from a child class.
1591 */
Namespace(ClassBase const * child)1592 explicit Namespace (ClassBase const* child)
1593 : L (child->L)
1594 , m_stackSize (0)
1595 #ifdef LUABINDINGDOC
1596 , _name (child->_parent ? child->_parent->_name : "")
1597 , _parent (child->_parent ? child->_parent->_parent : NULL)
1598 #endif
1599 {
1600 m_stackSize = child->m_stackSize - 3;
1601 child->m_stackSize = 3;
1602 child->pop (3);
1603 }
1604
1605 public:
1606 //----------------------------------------------------------------------------
1607 /**
1608 Copy Constructor.
1609
1610 Ownership of the stack is transferred to the new object. This happens
1611 when the compiler emits temporaries to hold these objects while chaining
1612 registrations across namespaces.
1613 */
Namespace(Namespace const & other)1614 Namespace (Namespace const& other) : L (other.L)
1615 {
1616 m_stackSize = other.m_stackSize;
1617 other.m_stackSize = 0;
1618 #ifdef LUABINDINGDOC
1619 _name = other._name;
1620 _parent = other._parent;
1621 #endif
1622 }
1623
1624 //----------------------------------------------------------------------------
1625 /**
1626 Closes this namespace registration.
1627 */
~Namespace()1628 ~Namespace ()
1629 {
1630 pop (m_stackSize);
1631 }
1632
1633 //----------------------------------------------------------------------------
1634 /**
1635 Open the global namespace.
1636 */
getGlobalNamespace(lua_State * L)1637 static Namespace getGlobalNamespace (lua_State* L)
1638 {
1639 return Namespace (L);
1640 }
1641
1642 //----------------------------------------------------------------------------
1643 /**
1644 Open a new or existing namespace for registrations.
1645 */
beginNamespace(char const * name)1646 Namespace beginNamespace (char const* name)
1647 {
1648 return Namespace (name, this);
1649 }
1650
1651 //----------------------------------------------------------------------------
1652 /**
1653 Continue namespace registration in the parent.
1654
1655 Do not use this on the global namespace.
1656 */
endNamespace()1657 Namespace endNamespace ()
1658 {
1659 return Namespace (this);
1660 }
1661
1662 //----------------------------------------------------------------------------
1663 /**
1664 Add or replace a variable.
1665 */
1666 template <class T>
1667 Namespace& addVariable (char const* name, T* pt, bool isWritable = true)
1668 {
1669 assert (lua_istable (L, -1));
1670
1671 rawgetfield (L, -1, "__propget");
1672 assert (lua_istable (L, -1));
1673 lua_pushlightuserdata (L, pt);
1674 lua_pushcclosure (L, &CFunc::getVariable <T>, 1);
1675 rawsetfield (L, -2, name);
1676 lua_pop (L, 1);
1677
1678 rawgetfield (L, -1, "__propset");
1679 assert (lua_istable (L, -1));
1680 if (isWritable)
1681 {
1682 lua_pushlightuserdata (L, pt);
1683 lua_pushcclosure (L, &CFunc::setVariable <T>, 1);
1684 }
1685 else
1686 {
1687 lua_pushstring (L, name);
1688 lua_pushcclosure (L, &CFunc::readOnlyError, 1);
1689 }
1690 rawsetfield (L, -2, name);
1691 lua_pop (L, 1);
1692
1693 return *this;
1694 }
1695
1696 template <typename U>
addConst(char const * name,const U val)1697 Namespace& addConst (char const* name, const U val)
1698 {
1699 DATADOC ("Constant/Enum", name, val)
1700 assert (lua_istable (L, -1));
1701 rawgetfield (L, -1, "__propget");
1702 new (lua_newuserdata (L, sizeof (val))) U (val);
1703 lua_pushcclosure (L, &CFunc::getConst <U>, 1);
1704 rawsetfield (L, -2, name);
1705 lua_pop (L, 1);
1706
1707 rawgetfield (L, -1, "__propset");
1708 assert (lua_istable (L, -1));
1709 lua_pushstring (L, name);
1710 lua_pushcclosure (L, &CFunc::readOnlyError, 1);
1711 rawsetfield (L, -2, name);
1712 lua_pop (L, 1);
1713 return *this;
1714 }
1715
1716 //----------------------------------------------------------------------------
1717 /**
1718 Add or replace a property.
1719
1720 If the set function is omitted or null, the property is read-only.
1721 */
1722 #if 0 // unused
1723 template <class TG, class TS>
1724 Namespace& addProperty (char const* name, TG (*get) (), void (*set)(TS) = 0)
1725 {
1726 assert (lua_istable (L, -1));
1727
1728 rawgetfield (L, -1, "__propget");
1729 assert (lua_istable (L, -1));
1730 typedef TG (*get_t) ();
1731 new (lua_newuserdata (L, sizeof (get_t))) get_t (get);
1732 lua_pushcclosure (L, &CFunc::Call <TG (*) (void)>::f, 1);
1733 rawsetfield (L, -2, name);
1734 lua_pop (L, 1);
1735
1736 rawgetfield (L, -1, "__propset");
1737 assert (lua_istable (L, -1));
1738 if (set != 0)
1739 {
1740 typedef void (*set_t) (TS);
1741 new (lua_newuserdata (L, sizeof (set_t))) set_t (set);
1742 lua_pushcclosure (L, &CFunc::Call <void (*) (TS)>::f, 1);
1743 }
1744 else
1745 {
1746 lua_pushstring (L, name);
1747 lua_pushcclosure (L, &CFunc::readOnlyError, 1);
1748 }
1749 rawsetfield (L, -2, name);
1750 lua_pop (L, 1);
1751
1752 return *this;
1753 }
1754 #endif
1755
1756 //----------------------------------------------------------------------------
1757 /**
1758 Add or replace a free function.
1759 */
1760 template <class FP>
addFunction(char const * name,FP const fp)1761 Namespace& addFunction (char const* name, FP const fp)
1762 {
1763 FUNDOC ("Free Function", name, FP)
1764 assert (lua_istable (L, -1));
1765
1766 new (lua_newuserdata (L, sizeof (fp))) FP (fp);
1767 lua_pushcclosure (L, &CFunc::Call <FP>::f, 1);
1768 rawsetfield (L, -2, name);
1769
1770 return *this;
1771 }
1772
1773 template <class FP>
addRefFunction(char const * name,FP const fp)1774 Namespace& addRefFunction (char const* name, FP const fp)
1775 {
1776 FUNDOC ("Free Function RefReturn", name, FP)
1777 assert (lua_istable (L, -1));
1778
1779 new (lua_newuserdata (L, sizeof (fp))) FP (fp);
1780 lua_pushcclosure (L, &CFunc::CallRef <FP>::f, 1);
1781 rawsetfield (L, -2, name);
1782
1783 return *this;
1784 }
1785
1786 //----------------------------------------------------------------------------
1787 /**
1788 Add or replace a array type
1789 */
1790
1791 template <typename T>
registerArray(char const * name)1792 Namespace registerArray (char const* name)
1793 {
1794 return Array <T> (name, this).endArray();
1795 }
1796
1797
1798 //----------------------------------------------------------------------------
1799 /**
1800 Add or replace a lua_CFunction.
1801 */
addCFunction(char const * name,int (* const fp)(lua_State *))1802 Namespace& addCFunction (char const* name, int (*const fp)(lua_State*))
1803 {
1804 DATADOC ("Free C Function", name, fp)
1805 lua_pushcfunction (L, fp);
1806 rawsetfield (L, -2, name);
1807
1808 return *this;
1809 }
1810
1811 //----------------------------------------------------------------------------
1812 /**
1813 Open a new or existing class for registrations.
1814 */
1815 template <class T>
beginClass(char const * name)1816 Class <T> beginClass (char const* name)
1817 {
1818 return Class <T> (name, this);
1819 }
1820
1821 /** weak & shared pointer class */
1822 template <class T>
beginWSPtrClass(char const * name)1823 WSPtrClass <T> beginWSPtrClass (char const* name)
1824 {
1825 return WSPtrClass <T> (name, this)
1826 .addNullCheck()
1827 .addEqualCheck();
1828 }
1829
1830 //----------------------------------------------------------------------------
1831
1832 template <class K, class V>
beginStdMap(char const * name)1833 Class<std::map<K, V> > beginStdMap (char const* name)
1834 {
1835 typedef std::map<K, V> LT;
1836 typedef std::pair<const K, V> T;
1837
1838 typedef typename std::map<K, V>::size_type T_SIZE;
1839
1840 return beginClass<LT> (name)
1841 .addVoidConstructor ()
1842 .addFunction ("empty", (bool (LT::*)()const)<::empty)
1843 .addFunction ("size", (T_SIZE (LT::*)()const)<::size)
1844 .addFunction ("clear", (void (LT::*)())<::clear)
1845 .addFunction ("count", (T_SIZE (LT::*)(const K&) const)<::count)
1846 .addExtCFunction ("add", &CFunc::tableToMap<K, V>)
1847 .addExtCFunction ("iter", &CFunc::mapIter<K, V>)
1848 .addExtCFunction ("table", &CFunc::mapToTable<K, V>)
1849 .addExtCFunction ("at", &CFunc::mapAt<K, V>);
1850 }
1851
1852 template <class T>
beginStdSet(char const * name)1853 Class<std::set<T> > beginStdSet (char const* name)
1854 {
1855 typedef std::set<T> LT;
1856 return beginClass<LT> (name)
1857 .addVoidConstructor ()
1858 .addFunction ("clear", (void (LT::*)())<::clear)
1859 .addFunction ("empty", <::empty)
1860 .addFunction ("size", <::size)
1861 .addExtCFunction ("iter", &CFunc::setIter<T, LT>)
1862 .addExtCFunction ("table", &CFunc::setToTable<T, LT>);
1863 }
1864
1865 template <unsigned int T>
beginStdBitSet(char const * name)1866 Class<std::bitset<T> > beginStdBitSet (char const* name)
1867 {
1868 typedef std::bitset<T> BS;
1869 return beginClass<BS> (name)
1870 .addVoidConstructor ()
1871 .addFunction ("reset", (BS& (BS::*)())&BS::reset)
1872 .addFunction ("set", (BS& (BS::*)(size_t, bool))&BS::set)
1873 .addFunction ("count", (size_t (BS::*)()const)&BS::count)
1874 .addFunction ("size", (size_t (BS::*)()const)&BS::size)
1875 .addFunction ("any", (bool (BS::*)()const)&BS::any)
1876 .addFunction ("none", (bool (BS::*)()const)&BS::none)
1877 .addFunction ("test", &BS::test)
1878 .addExtCFunction ("add", &CFunc::tableToBitSet<T>)
1879 .addExtCFunction ("table", &CFunc::bitSetToTable<T>);
1880 }
1881
1882 template <class T>
beginConstStdList(char const * name)1883 Class<std::list<T> > beginConstStdList (char const* name)
1884 {
1885 typedef std::list<T> LT;
1886 typedef typename LT::size_type T_SIZE;
1887 return beginClass<LT> (name)
1888 .addVoidConstructor ()
1889 .addFunction ("empty", static_cast<bool (LT::*)() const>(<::empty))
1890 .addFunction ("size", static_cast<T_SIZE (LT::*)() const>(<::size))
1891 .addFunction ("reverse", static_cast<void (LT::*)()>(<::reverse))
1892 .addFunction ("front", static_cast<T& (LT::*)()>(<::front))
1893 .addFunction ("back", static_cast<T& (LT::*)()>(<::back))
1894 .addExtCFunction ("iter", &CFunc::listIter<T, LT>)
1895 .addExtCFunction ("table", &CFunc::listToTable<T, LT>);
1896 }
1897
1898 template <class T>
beginStdList(char const * name)1899 Class<std::list<T> > beginStdList (char const* name)
1900 {
1901 typedef std::list<T> LT;
1902 typedef typename LT::size_type T_SIZE;
1903 return beginConstStdList<T> (name)
1904 #if !defined(_MSC_VER) || (_MSC_VER < 1900)
1905 /* std::list::unique() got broken in later versions of MSVC */
1906 # if (defined(__cplusplus) && __cplusplus >= 201709L)
1907 .addFunction ("unique", (T_SIZE (LT::*)())<::unique)
1908 # else
1909 .addFunction ("unique", (void (LT::*)())<::unique)
1910 # endif
1911 #endif
1912 .addFunction ("push_back", (void (LT::*)(const T&))<::push_back)
1913 .addExtCFunction ("add", &CFunc::tableToList<T, LT>);
1914 }
1915
1916 template <class T>
beginConstStdCPtrList(char const * name)1917 Class<std::list<T*> > beginConstStdCPtrList (char const* name)
1918 {
1919 typedef T* TP;
1920 typedef std::list<TP> LT;
1921 typedef typename LT::size_type T_SIZE;
1922 return beginClass<LT> (name)
1923 .addVoidConstructor ()
1924 .addFunction ("empty", static_cast<bool (LT::*)() const>(<::empty))
1925 .addFunction ("size", static_cast<T_SIZE (LT::*)() const>(<::size))
1926 .addFunction ("reverse", static_cast<void (LT::*)()>(<::reverse))
1927 .addFunction ("front", static_cast<const TP& (LT::*)() const>(<::front))
1928 .addFunction ("back", static_cast<const TP& (LT::*)() const>(<::back))
1929 .addExtCFunction ("iter", &CFunc::listIter<T*, LT>)
1930 .addExtCFunction ("table", &CFunc::listToTable<T*, LT>);
1931 }
1932
1933 template <class T>
beginStdCPtrList(char const * name)1934 Class<std::list<T*> > beginStdCPtrList (char const* name)
1935 {
1936 typedef T* TP;
1937 typedef std::list<TP> LT;
1938 typedef typename LT::size_type T_SIZE;
1939 return beginConstStdCPtrList<T> (name)
1940 #if !defined(_MSC_VER) || (_MSC_VER < 1900)
1941 /* std::list::unique() got broken in later versions of MSVC */
1942 # if (defined(__cplusplus) && __cplusplus >= 201709L)
1943 .addFunction ("unique", (T_SIZE (LT::*)())<::unique)
1944 # else
1945 .addFunction ("unique", (void (LT::*)())<::unique)
1946 # endif
1947 #endif
1948 .addExtCFunction ("push_back", &CFunc::pushbackptr<T, LT>);
1949 }
1950
1951
1952 template <class T>
beginConstStdVector(char const * name)1953 Class<std::vector<T> > beginConstStdVector (char const* name)
1954 {
1955 typedef std::vector<T> LT;
1956 typedef typename std::vector<T>::reference T_REF;
1957 typedef typename std::vector<T>::size_type T_SIZE;
1958
1959 return beginClass<LT> (name)
1960 .addVoidConstructor ()
1961 .addFunction ("empty", (bool (LT::*)()const)<::empty)
1962 .addFunction ("size", (T_SIZE (LT::*)()const)<::size)
1963 .addFunction ("at", (T_REF (LT::*)(T_SIZE))<::at)
1964 .addExtCFunction ("iter", &CFunc::listIter<T, LT>)
1965 .addExtCFunction ("table", &CFunc::listToTable<T, LT>);
1966 }
1967
1968 template <class T>
beginStdVector(char const * name)1969 Class<std::vector<T> > beginStdVector (char const* name)
1970 {
1971 typedef std::vector<T> LT;
1972 return beginConstStdVector<T> (name)
1973 .addVoidConstructor ()
1974 .addFunction ("push_back", (void (LT::*)(const T&))<::push_back)
1975 .addFunction ("clear", (void (LT::*)())<::clear)
1976 .addExtCFunction ("to_array", &CFunc::vectorToArray<T, LT>)
1977 .addExtCFunction ("add", &CFunc::tableToList<T, LT>);
1978 }
1979
1980 //----------------------------------------------------------------------------
1981
1982 template <class T>
beginPtrStdList(char const * name)1983 Class<boost::shared_ptr<std::list<T> > > beginPtrStdList (char const* name)
1984 {
1985 typedef std::list<T> LT;
1986 typedef typename LT::size_type T_SIZE;
1987 return beginClass<boost::shared_ptr<LT> > (name)
1988 //.addVoidPtrConstructor<LT> ()
1989 .addPtrFunction ("empty", (bool (LT::*)()const)<::empty)
1990 .addPtrFunction ("size", (T_SIZE (LT::*)()const)<::size)
1991 .addPtrFunction ("reverse", (void (LT::*)())<::reverse)
1992 #if !defined(_MSC_VER) || (_MSC_VER < 1900)
1993 /* std::list::unique() got broken in later versions of MSVC */
1994 # if (defined(__cplusplus) && __cplusplus >= 201709L)
1995 .addPtrFunction ("unique", (T_SIZE (LT::*)())<::unique)
1996 # else
1997 .addPtrFunction ("unique", (void (LT::*)())<::unique)
1998 # endif
1999 #endif
2000 .addPtrFunction ("push_back", (void (LT::*)(const T&))<::push_back)
2001 .addExtCFunction ("add", &CFunc::ptrTableToList<T, LT>)
2002 .addExtCFunction ("iter", &CFunc::ptrListIter<T, LT>)
2003 .addExtCFunction ("table", &CFunc::ptrListToTable<T, LT>);
2004 }
2005
2006 template <class T>
beginPtrStdVector(char const * name)2007 Class<boost::shared_ptr<std::vector<T> > > beginPtrStdVector (char const* name)
2008 {
2009 typedef std::vector<T> LT;
2010 typedef typename std::vector<T>::reference T_REF;
2011 typedef typename std::vector<T>::size_type T_SIZE;
2012
2013 return beginClass<boost::shared_ptr<LT> > (name)
2014 //.addVoidPtrConstructor<LT> ()
2015 .addPtrFunction ("empty", (bool (LT::*)()const)<::empty)
2016 .addPtrFunction ("size", (T_SIZE (LT::*)()const)<::size)
2017 .addPtrFunction ("push_back", (void (LT::*)(const T&))<::push_back)
2018 .addPtrFunction ("at", (T_REF (LT::*)(T_SIZE))<::at)
2019 .addExtCFunction ("add", &CFunc::ptrTableToList<T, LT>)
2020 .addExtCFunction ("iter", &CFunc::ptrListIter<T, LT>)
2021 .addExtCFunction ("table", &CFunc::ptrListToTable<T, LT>);
2022 }
2023
2024 //----------------------------------------------------------------------------
2025 /**
2026 Derive a new class for registrations.
2027
2028 To continue registrations for the class later, use beginClass().
2029 Do not call deriveClass() again.
2030 */
2031 template <class T, class U>
deriveClass(char const * name)2032 Class <T> deriveClass (char const* name)
2033 {
2034 CLASSDOC ("[C] Derived Class", _name << name, type_name <T>(), type_name <U>())
2035 return Class <T> (name, this, ClassInfo <U>::getStaticKey ());
2036 }
2037
2038 template <class T, class U>
deriveWSPtrClass(char const * name)2039 WSPtrClass <T> deriveWSPtrClass (char const* name)
2040 {
2041
2042 CLASSDOC ("[C] Derived Class", _name << name, type_name <boost::shared_ptr<T> >(), type_name <boost::shared_ptr<U> >())
2043 CLASSDOC ("[C] Derived Class", _name << name, type_name <boost::weak_ptr<T> >(), type_name <boost::weak_ptr<U> >())
2044 CLASSDOC ("[C] Derived Pointer Class", _name << name, type_name <T>(), type_name <U>())
2045 return WSPtrClass <T> (name, this,
2046 ClassInfo <boost::shared_ptr<U> >::getStaticKey (),
2047 ClassInfo <boost::weak_ptr<U> >::getStaticKey ())
2048 .addNullCheck()
2049 .addEqualCheck();
2050 }
2051
2052 };
2053
2054 //------------------------------------------------------------------------------
2055 /**
2056 Retrieve the global namespace.
2057
2058 It is recommended to put your namespace inside the global namespace, and
2059 then add your classes and functions to it, rather than adding many classes
2060 and functions directly to the global namespace.
2061 */
getGlobalNamespace(lua_State * L)2062 inline Namespace getGlobalNamespace (lua_State* L)
2063 {
2064 return Namespace::getGlobalNamespace (L);
2065 }
2066
2067
2068 #undef KEYSTA
2069 #undef KEYEND
2070 #undef CLASSDOC
2071 #undef PRINTDOC
2072 #undef FUNDOC
2073 #undef DATADOC
2074
2075 /* vim: set et sw=2: */
2076