1 #include "lua-base.hpp"
2 #include "lua-class.hpp"
3 #include "lua-function.hpp"
4 #include "lua-params.hpp"
6 #include "stateobject.hpp"
16 threads::rlock
* global_lock
;
17 threads::rlock
& get_lua_lock()
19 if(!global_lock
) global_lock
= new threads::rlock
;
25 std::map
<std::string
, state::callback_list
*> callbacks
;
26 std::set
<std::pair
<function_group
*, int>> function_groups
;
27 std::set
<std::pair
<class_group
*, int>> class_groups
;
30 struct fgroup_internal
36 std::map
<std::string
, function
*> functions
;
38 std::map
<int, std::function
<void(std::string
, function
*)>> callbacks
;
39 std::map
<int, std::function
<void(function_group
*)>> dcallbacks
;
42 struct cgroup_internal
49 std::map
<std::string
, class_base
*> classes
;
50 std::map
<int, std::function
<void(std::string
, class_base
*)>> callbacks
;
51 std::map
<int, std::function
<void(class_group
*)>> dcallbacks
;
54 typedef stateobject::type
<state
, state_internal
> state_internal_t
;
55 typedef stateobject::type
<function_group
, fgroup_internal
> fgroup_internal_t
;
56 typedef stateobject::type
<class_group
, cgroup_internal
> cgroup_internal_t
;
59 std::unordered_map
<std::type_index
, void*>& class_types()
61 static std::unordered_map
<std::type_index
, void*> x
;
67 char classtable_meta_key
;
72 static int index(state
& L
);
73 static int newindex(state
& L
);
74 static int pairs(state
& L
);
75 static int pairs_next(state
& L
);
76 static int smethods(state
& L
);
77 static int cmethods(state
& L
);
78 static int trampoline(state
& L
);
79 static void check(state
& L
);
82 void class_info::check(state
& L
)
84 L
.pushlightuserdata(&classtable_meta_key
);
85 L
.rawget(LUA_REGISTRYINDEX
);
87 if(!L
.rawequal(-1, -2))
88 throw std::runtime_error("Bad class table");
92 int class_info::index(state
& L
)
96 class_base
* ptr
= ((class_info
*)L
.touserdata(1))->obj
;
97 const char* method
= L
.tostring(2);
99 throw std::runtime_error("Indexing invalid element of class table");
100 if(!strcmp(method
, "_static_methods")) {
101 L
.pushlightuserdata(ptr
);
102 L
.push_trampoline(class_info::smethods
, 1);
104 } else if(!strcmp(method
, "_class_methods")) {
105 L
.pushlightuserdata(ptr
);
106 L
.push_trampoline(class_info::cmethods
, 1);
109 auto m
= ptr
->static_methods();
111 if(!strcmp(i
.name
, method
)) {
113 std::string fname
= ptr
->get_name() + "::" + i
.name
;
114 L
.pushlightuserdata((void*)i
.fn
);
115 L
.pushstring(fname
.c_str());
116 L
.push_trampoline(class_info::trampoline
, 2);
120 std::string err
= std::string("Class '") + ptr
->get_name() +
121 "' does not have static method '" + method
+ "'";
122 throw std::runtime_error(err
);
124 return 0; //NOTREACHED
126 int class_info::newindex(state
& L
)
128 throw std::runtime_error("Writing into class table not allowed");
131 int class_info::pairs(state
& L
)
135 L
.push_trampoline(class_info::pairs_next
, 0); //Next.
136 L
.pushvalue(1); //State.
137 L
.pushnil(); //Index.
141 int class_info::pairs_next(state
& L
)
145 class_base
* obj
= ((class_info
*)L
.touserdata(1))->obj
;
146 auto m
= obj
->static_methods();
147 std::string key
= (L
.type(2) == LUA_TSTRING
) ? L
.tostring(2) : "";
148 std::string lowbound
= "\xFF"; //Sorts greater than anything that is valid UTF-8.
149 void* best_fn
= NULL
;
151 if(lowbound
> i
.name
&& i
.name
> key
) {
153 best_fn
= (void*)i
.fn
;
156 L
.pushlstring(lowbound
);
157 std::string name
= obj
->get_name() + "::" + lowbound
;
158 L
.pushlightuserdata(best_fn
);
160 L
.push_trampoline(class_info::trampoline
, 2);
168 int class_info::smethods(state
& L
)
170 class_base
* obj
= (class_base
*)L
.touserdata(L
.trampoline_upval(1));
171 auto m
= obj
->static_methods();
174 L
.pushstring(i
.name
);
180 int class_info::cmethods(state
& L
)
182 class_base
* obj
= (class_base
*)L
.touserdata(L
.trampoline_upval(1));
183 auto m
= obj
->class_methods();
186 L
.pushstring(i
.c_str());
192 typedef int (*fn_t
)(state
& L
, parameters
& P
);
193 typedef int (*fnraw_t
)(state
& L
);
196 //1) Pointer to function control block.
197 //2) Pointer to method name.
198 int class_info::trampoline(state
& L
)
200 void* _fn
= L
.touserdata(L
.trampoline_upval(1));
202 std::string name
= L
.tostring(L
.trampoline_upval(2));
203 parameters
P(L
, name
);
208 //1) Pointer to function control block.
209 int lua_trampoline_function(state
& L
)
211 void* ptr
= L
.touserdata(L
.trampoline_upval(1));
212 function
* f
= reinterpret_cast<function
*>(ptr
);
217 //1) Pointer to master state.
218 //2) Poiinter to function to call.
219 int lua_main_trampoline(lua_State
* L
)
221 state
* lstate
= reinterpret_cast<state
*>(lua_touserdata(L
, lua_upvalueindex(1)));
222 void* _fn
= lua_touserdata(L
, lua_upvalueindex(2));
223 fnraw_t fn
= (fnraw_t
)_fn
;
224 //The function is always run in non-set_interruptable mode.
226 state
_L(*lstate
, L
);
227 lstate
->set_interruptable_flag(false);
229 lstate
->set_interruptable_flag(true);
231 } catch(std::exception
& e
) {
232 lua_pushfstring(L
, "%s", e
.what());
233 lstate
->set_interruptable_flag(true);
239 //Pushes given table to top of stack, creating if needed.
240 void recursive_lookup_table(state
& L
, const std::string
& tab
)
244 assert(L
.type(-1) == LUA_TTABLE
);
248 size_t split
= u
.find_last_of(".");
251 if(split
< u
.length()) {
252 u1
= u
.substr(0, split
);
253 u2
= u
.substr(split
+ 1);
255 recursive_lookup_table(L
, u1
);
256 L
.getfield(-1, u2
.c_str());
257 if(L
.type(-1) != LUA_TTABLE
) {
258 //Not a table, create a table.
261 L
.setfield(-2, u2
.c_str());
262 L
.getfield(-1, u2
.c_str());
264 //Get rid of previous table.
269 void register_function(state
& L
, const std::string
& name
, function
* fun
)
271 std::string u
= name
;
272 size_t split
= u
.find_last_of(".");
275 if(split
< u
.length()) {
276 u1
= u
.substr(0, split
);
277 u2
= u
.substr(split
+ 1);
279 recursive_lookup_table(L
, u1
);
283 void* ptr
= reinterpret_cast<void*>(fun
);
284 L
.pushlightuserdata(ptr
);
285 L
.push_trampoline(lua_trampoline_function
, 1);
287 L
.setfield(-2, u2
.c_str());
291 void register_class(state
& L
, const std::string
& name
, class_base
* fun
)
293 fun
->register_state(L
);
296 int run_interruptable_trampoline(lua_State
* L
)
298 //Be very careful with faults here! We are running in interruptable context.
299 static std::string err
;
300 auto& fn
= *(std::function
<void()>*)lua_touserdata(L
, -1);
301 int out
= lua_tonumber(L
, -2);
302 lua_pop(L
, 2); //fn is passed as a pointer, so popping it is OK.
305 } catch(std::exception
& e
) {
307 //This can fault, so err is static.
308 lua_pushlstring(L
, err
.c_str(), err
.length());
319 oom_handler
= builtin_oom
;
320 soft_oom_handler
= builtin_soft_oom
;
321 interruptable
= false; //Assume initially not interruptable.
322 memory_limit
= (size_t)-1; //Unlimited.
326 state::state(state
& _master
, lua_State
* L
)
332 state::~state() throw()
336 threads::arlock
h(get_lua_lock());
337 auto state
= state_internal_t::get_soft(this);
339 for(auto i
: state
->function_groups
)
340 i
.first
->drop_callback(i
.second
);
341 for(auto i
: state
->class_groups
)
342 i
.first
->drop_callback(i
.second
);
344 lua_close(lua_handle
);
345 state_internal_t::clear(this);
348 void state::builtin_oom()
350 std::cerr
<< "PANIC: FATAL: Out of memory" << std::endl
;
354 void state::builtin_soft_oom(int status
)
357 std::cerr
<< "Lua: Memory limit exceeded, attempting to free memory..." << std::endl
;
359 std::cerr
<< "Lua: Memory allocation still failed." << std::endl
;
361 std::cerr
<< "Lua: Allocation successful after freeing some memory." << std::endl
;
364 void* state::builtin_alloc(void* user
, void* old
, size_t olds
, size_t news
)
367 auto& st
= *reinterpret_cast<state
*>(user
);
369 if(news
> olds
&& !st
.charge_memory(news
- olds
, false)) {
370 goto retry_allocation
;
372 m
= realloc(old
, news
);
373 if(!m
&& !st
.get_interruptable_flag())
376 st
.charge_memory(news
- olds
, true); //Undo commit.
377 goto retry_allocation
;
380 st
.charge_memory(olds
- news
, true); //Release memory.
381 if(m
&& st
.memory_change
) st
.memory_change((ssize_t
)news
- (ssize_t
)olds
);
384 st
.charge_memory(olds
, true); //Release memory.
385 if(st
.memory_change
) st
.memory_change(-(ssize_t
)olds
);
390 st
.soft_oom_handler(0);
391 st
.interruptable
= false; //Give everything we got for the GC.
392 lua_gc(st
.lua_handle
, LUA_GCCOLLECT
,0); //Do full cycle to try to free some memory.
393 st
.interruptable
= true;
394 if(!st
.charge_memory(news
- olds
, false)) { //Try to see if memory can be allocated.
395 st
.soft_oom_handler(-1);
398 m
= realloc(old
, news
);
399 if(!m
&& news
> olds
)
400 st
.charge_memory(news
- olds
, true); //Undo commit.
401 st
.soft_oom_handler(m
? 1 : -1);
402 if(m
&& st
.memory_change
) st
.memory_change((ssize_t
)news
- (ssize_t
)olds
);
406 void state::push_trampoline(int(*fn
)(state
& L
), unsigned n_upvals
)
408 lua_pushlightuserdata(lua_handle
, (void*)&get_master());
409 lua_pushlightuserdata(lua_handle
, (void*)fn
);
411 lua_insert(lua_handle
, -(int)n_upvals
- 2);
412 lua_insert(lua_handle
, -(int)n_upvals
- 2);
414 lua_pushcclosure(lua_handle
, lua_main_trampoline
, trampoline_upvals
+ n_upvals
);
417 //Lua 5.1 doesn't define LUA_OK.
422 void state::run_interruptable(std::function
<void()> fn
, unsigned in
, unsigned out
)
425 pushlightuserdata(&fn
);
426 pushcfunction(run_interruptable_trampoline
);
427 insert(-(int)in
- 3);
428 int r
= pcall(in
+ 2, out
, 0);
431 } else if(r
== LUA_ERRRUN
) {
432 throw std::runtime_error(tostring(-1));
433 } else if(r
== LUA_ERRMEM
) {
434 throw std::runtime_error("Lua out of memory");
435 } else if(r
== LUA_ERRERR
) {
436 throw std::runtime_error("Lua double fault");
438 } else if(r
== LUA_ERRGCMM
) {
439 throw std::runtime_error("Lua fault in garbage collector");
444 bool state::charge_memory(size_t amount
, bool release
)
446 if(master
) return master
->charge_memory(amount
, release
);
448 if(memory_use
> amount
)
449 memory_use
-= amount
;
455 //Give everything we got.
456 memory_use
+= amount
;
459 //Check limit and refuse allocations too large.
460 if(memory_use
+ amount
> memory_limit
|| memory_use
+ amount
< amount
)
462 memory_use
+= amount
;
467 function::function(function_group
& _group
, const std::string
& func
)
470 group
.do_register(fname
= func
, *this);
473 function::~function() throw()
475 group
.do_unregister(fname
, *this);
478 class_base::class_base(class_group
& _group
, const std::string
& _name
)
479 : group(_group
), name(_name
)
484 class_base::~class_base() throw()
487 group
.do_unregister(name
, *this);
493 return master
->reset();
494 threads::arlock
h(get_lua_lock());
495 auto state
= &state_internal_t::get(this);
497 lua_State
* tmp
= lua_newstate(state::builtin_alloc
, this);
499 throw std::runtime_error("Can't re-initialize Lua interpretter");
500 lua_close(lua_handle
);
501 for(auto& i
: state
->callbacks
)
506 lua_handle
= lua_newstate(state::builtin_alloc
, this);
508 throw std::runtime_error("Can't initialize Lua interpretter");
510 for(auto i
: state
->function_groups
)
511 i
.first
->request_callback([this](std::string name
, function
* func
) -> void {
512 register_function(*this, name
, func
);
514 for(auto i
: state
->class_groups
)
515 i
.first
->request_callback([this](std::string name
, class_base
* clazz
) -> void {
516 register_class(*this, name
, clazz
);
520 void state::deinit() throw()
523 return master
->deinit();
525 lua_close(lua_handle
);
529 void state::add_function_group(function_group
& group
)
531 threads::arlock
h(get_lua_lock());
532 auto& state
= state_internal_t::get(this);
533 state
.function_groups
.insert(std::make_pair(&group
, group
.add_callback([this](const std::string
& name
,
534 function
* func
) -> void {
535 this->function_callback(name
, func
);
536 }, [this](function_group
* x
) {
537 threads::arlock
h(get_lua_lock());
538 auto state
= state_internal_t::get_soft(this);
540 for(auto i
= state
->function_groups
.begin(); i
!= state
->function_groups
.end();)
542 i
= state
->function_groups
.erase(i
);
548 void state::add_class_group(class_group
& group
)
550 threads::arlock
h(get_lua_lock());
551 auto& state
= state_internal_t::get(this);
552 state
.class_groups
.insert(std::make_pair(&group
, group
.add_callback([this](const std::string
& name
,
553 class_base
* clazz
) -> void {
554 this->class_callback(name
, clazz
);
555 }, [this](class_group
* x
) {
556 threads::arlock
h(get_lua_lock());
557 auto state
= state_internal_t::get_soft(this);
559 for(auto i
= state
->class_groups
.begin(); i
!= state
->class_groups
.end();)
561 i
= state
->class_groups
.erase(i
);
567 void state::function_callback(const std::string
& name
, function
* func
)
570 return master
->function_callback(name
, func
);
572 register_function(*this, name
, func
);
575 void state::class_callback(const std::string
& name
, class_base
* clazz
)
578 return master
->class_callback(name
, clazz
);
580 register_class(*this, name
, clazz
);
583 bool state::do_once(void* key
)
586 return master
->do_once(key
);
587 pushlightuserdata(key
);
588 rawget(LUA_REGISTRYINDEX
);
589 if(type(-1) == LUA_TNIL
) {
591 pushlightuserdata(key
);
592 pushlightuserdata(key
);
593 rawset(LUA_REGISTRYINDEX
);
601 std::list
<state::callback_list
*> state::get_callbacks()
604 return master
->get_callbacks();
605 threads::arlock
h(get_lua_lock());
606 auto state
= state_internal_t::get_soft(this);
607 std::list
<callback_list
*> r
;
609 for(auto i
: state
->callbacks
)
610 r
.push_back(i
.second
);
614 void state::do_register(const std::string
& name
, callback_list
& callback
)
616 threads::arlock
h(get_lua_lock());
617 auto& state
= state_internal_t::get(this);
618 if(state
.callbacks
.count(name
)) return;
619 state
.callbacks
[name
] = &callback
;
622 void state::do_unregister(const std::string
& name
, callback_list
& callback
)
624 threads::arlock
h(get_lua_lock());
625 auto state
= state_internal_t::get_soft(this);
626 if(state
&& state
->callbacks
.count(name
) && state
->callbacks
[name
] == &callback
)
627 state
->callbacks
.erase(name
);
630 state::callback_list::callback_list(state
& _L
, const std::string
& _name
, const std::string
& fncbname
)
631 : L(_L
), name(_name
), fn_cbname(fncbname
)
634 running_cb_f
= false;
635 L
.do_register(name
, *this);
638 state::callback_list::~callback_list()
640 L
.do_unregister(name
, *this);
643 for(auto& i
: callbacks
) {
644 L
.pushlightuserdata(&i
);
646 L
.rawset(LUA_REGISTRYINDEX
);
650 void state::callback_list::_register(state
& _L
)
652 callbacks
.push_back(0);
653 _L
.pushlightuserdata(&*callbacks
.rbegin());
655 _L
.rawset(LUA_REGISTRYINDEX
);
658 void state::callback_list::_unregister(state
& _L
)
660 for(auto i
= callbacks
.begin(); i
!= callbacks
.end();) {
661 _L
.pushlightuserdata(&*i
);
662 _L
.rawget(LUA_REGISTRYINDEX
);
663 if(_L
.rawequal(-1, -2)) {
665 _L
.pushlightuserdata(key
);
667 _L
.rawset(LUA_REGISTRYINDEX
);
668 if(running_cb
== &*i
) {
669 //Unregistering currently running callback. Delay erasing the node until the
670 //callback finishes to avoid crashes.
674 i
= callbacks
.erase(i
);
682 function_group::function_group()
686 function_group::~function_group()
688 threads::arlock
h(get_lua_lock());
689 auto state
= fgroup_internal_t::get_soft(this);
691 for(auto i
: state
->dcallbacks
)
693 fgroup_internal_t::clear(this);
696 void function_group::request_callback(std::function
<void(std::string
, function
*)> cb
)
698 threads::arlock
h(get_lua_lock());
699 auto state
= fgroup_internal_t::get_soft(this);
701 for(auto i
: state
->functions
)
702 cb(i
.first
, i
.second
);
705 int function_group::add_callback(std::function
<void(std::string
, function
*)> cb
,
706 std::function
<void(function_group
*)> dcb
)
708 threads::arlock
h(get_lua_lock());
709 auto& state
= fgroup_internal_t::get(this);
710 int handle
= state
.next_handle
++;
711 state
.callbacks
[handle
] = cb
;
712 state
.dcallbacks
[handle
] = dcb
;
713 for(auto i
: state
.functions
)
714 cb(i
.first
, i
.second
);
718 void function_group::drop_callback(int handle
)
720 threads::arlock
h(get_lua_lock());
721 auto state
= fgroup_internal_t::get_soft(this);
723 state
->callbacks
.erase(handle
);
726 void function_group::do_register(const std::string
& name
, function
& fun
)
728 threads::arlock
h(get_lua_lock());
729 auto& state
= fgroup_internal_t::get(this);
730 if(state
.functions
.count(name
)) return;
731 state
.functions
[name
] = &fun
;
732 for(auto i
: state
.callbacks
)
733 i
.second(name
, &fun
);
736 void function_group::do_unregister(const std::string
& name
, function
& fun
)
738 threads::arlock
h(get_lua_lock());
739 auto state
= fgroup_internal_t::get_soft(this);
740 if(!state
|| !state
->functions
.count(name
) || state
->functions
[name
] != &fun
) return;
741 state
->functions
.erase(name
);
742 for(auto i
: state
->callbacks
)
743 i
.second(name
, NULL
);
746 class_group::class_group()
750 class_group::~class_group()
752 threads::arlock
h(get_lua_lock());
753 auto state
= cgroup_internal_t::get_soft(this);
755 for(auto i
: state
->dcallbacks
)
757 cgroup_internal_t::clear(this);
760 void class_group::request_callback(std::function
<void(std::string
, class_base
*)> cb
)
762 threads::arlock
h(get_lua_lock());
763 auto state
= cgroup_internal_t::get_soft(this);
765 for(auto i
: state
->classes
)
766 cb(i
.first
, i
.second
);
769 int class_group::add_callback(std::function
<void(std::string
, class_base
*)> cb
,
770 std::function
<void(class_group
*)> dcb
)
772 threads::arlock
h(get_lua_lock());
773 auto& state
= cgroup_internal_t::get(this);
774 int handle
= state
.next_handle
++;
775 state
.callbacks
[handle
] = cb
;
776 state
.dcallbacks
[handle
] = dcb
;
777 for(auto i
: state
.classes
)
778 cb(i
.first
, i
.second
);
782 void class_group::drop_callback(int handle
)
784 threads::arlock
h(get_lua_lock());
785 auto state
= cgroup_internal_t::get_soft(this);
787 state
->callbacks
.erase(handle
);
790 void class_group::do_register(const std::string
& name
, class_base
& fun
)
792 threads::arlock
h(get_lua_lock());
793 auto& state
= cgroup_internal_t::get(this);
794 if(state
.classes
.count(name
)) return;
795 state
.classes
[name
] = &fun
;
796 for(auto i
: state
.callbacks
)
797 i
.second(name
, &fun
);
800 void class_group::do_unregister(const std::string
& name
, class_base
& fun
)
802 threads::arlock
h(get_lua_lock());
803 auto state
= cgroup_internal_t::get_soft(this);
804 if(!state
|| !state
->classes
.count(name
) || state
->classes
[name
] != &fun
) return;
805 state
->classes
.erase(name
);
806 for(auto i
: state
->callbacks
)
807 i
.second(name
, NULL
);
810 std::list
<class_ops
>& userdata_recogn_fns()
812 static std::list
<class_ops
> x
;
816 std::string
try_recognize_userdata(state
& state
, int index
)
818 for(auto i
: userdata_recogn_fns())
819 if(i
.is(state
, index
))
821 //Hack: Lua builtin file objects and classobjs.
822 if(state
.getmetatable(index
)) {
823 state
.pushstring("FILE*");
824 state
.rawget(LUA_REGISTRYINDEX
);
825 if(state
.rawequal(-1, -2)) {
830 state
.pushlightuserdata(&classtable_meta_key
);
831 state
.rawget(LUA_REGISTRYINDEX
);
832 if(state
.rawequal(-1, -2)) {
841 std::string
try_print_userdata(state
& L
, int index
)
843 for(auto i
: userdata_recogn_fns())
845 return i
.print(L
, index
);
847 if(L
.getmetatable(index
)) {
848 L
.pushlightuserdata(&classtable_meta_key
);
849 L
.rawget(LUA_REGISTRYINDEX
);
850 if(L
.rawequal(-1, -2)) {
852 std::string cname
= ((class_info
*)L
.touserdata(index
))->obj
->get_name();
857 return "no data available";
860 int state::vararg_tag::pushargs(state
& L
)
868 else if(i
== "false")
869 L
.pushboolean(false);
870 else if(regex_match("[+-]?(|0|[1-9][0-9]*)(.[0-9]+)?([eE][+-]?(0|[1-9][0-9]*))?", i
))
871 L
.pushnumber(strtod(i
.c_str(), NULL
));
873 L
.pushlstring(i
.substr(1));
881 class_base
* class_base::lookup(state
& L
, const std::string
& _name
)
883 if(lookup_and_push(L
, _name
)) {
884 class_base
* obj
= ((class_info
*)L
.touserdata(-1))->obj
;
891 bool class_base::lookup_and_push(state
& L
, const std::string
& _name
)
893 L
.pushlightuserdata(&classtable_key
);
894 L
.rawget(LUA_REGISTRYINDEX
);
895 if(L
.type(-1) == LUA_TNIL
) {
900 //On top of stack there is class table.
901 L
.pushlstring(_name
);
903 if(L
.type(-1) == LUA_TNIL
) {
913 std::set
<std::string
> class_base::all_classes(state
& L
)
915 L
.pushlightuserdata(&classtable_key
);
916 L
.rawget(LUA_REGISTRYINDEX
);
917 if(L
.type(-1) == LUA_TNIL
) {
920 return std::set
<std::string
>();
922 std::set
<std::string
> r
;
925 L
.pop(1); //Pop value.
926 if(L
.type(-1) == LUA_TSTRING
) r
.insert(L
.tostring(-1));
932 void class_base::register_static(state
& L
)
935 L
.pushlightuserdata(&classtable_key
);
936 L
.rawget(LUA_REGISTRYINDEX
);
937 if(L
.type(-1) == LUA_TNIL
) {
939 L
.pushlightuserdata(&classtable_key
);
941 L
.rawset(LUA_REGISTRYINDEX
);
944 //On top of stack there is class table.
947 if(L
.type(-1) != LUA_TNIL
) {
948 //Already registered.
954 //Now construct the object.
955 class_info
* ci
= (class_info
*)L
.newuserdata(sizeof(class_info
));
958 L
.pushlightuserdata(&classtable_meta_key
);
959 L
.rawget(LUA_REGISTRYINDEX
);
960 if(L
.type(-1) == LUA_TNIL
) {
962 L
.pushlightuserdata(&classtable_meta_key
);
964 L
.pushstring("__index");
965 L
.push_trampoline(class_info::index
, 0);
967 L
.pushstring("__newindex");
968 L
.push_trampoline(class_info::newindex
, 0);
970 L
.pushstring("__pairs");
971 L
.push_trampoline(class_info::pairs
, 0);
973 L
.rawset(LUA_REGISTRYINDEX
);
981 void class_base::delayed_register()
983 group
.do_register(name
, *this);
986 functions::functions(function_group
& grp
, const std::string
& basetable
, std::initializer_list
<entry
> fnlist
)
988 std::string base
= (basetable
== "") ? "" : (basetable
+ ".");
990 funcs
.insert(new fn(grp
, base
+ i
.name
, i
.func
));
993 functions::~functions()
999 functions::fn::fn(function_group
& grp
, const std::string
& name
, std::function
<int(state
& L
, parameters
& P
)> _func
)
1000 : function(grp
, name
)
1005 functions::fn::~fn() throw()
1009 int functions::fn::invoke(state
& L
)
1011 lua::parameters
P(L
, fname
);