1 #include "lua-base.hpp"
2 #include "lua-class.hpp"
3 #include "lua-function.hpp"
4 #include "lua-params.hpp"
6 #include "stateobject.hpp"
15 threads::rlock
* global_lock
;
16 threads::rlock
& get_lua_lock()
18 if(!global_lock
) global_lock
= new threads::rlock
;
24 std::map
<std::string
, state::callback_list
*> callbacks
;
25 std::set
<std::pair
<function_group
*, int>> function_groups
;
26 std::set
<std::pair
<class_group
*, int>> class_groups
;
29 struct fgroup_internal
35 std::map
<std::string
, function
*> functions
;
37 std::map
<int, std::function
<void(std::string
, function
*)>> callbacks
;
38 std::map
<int, std::function
<void(function_group
*)>> dcallbacks
;
41 struct cgroup_internal
48 std::map
<std::string
, class_base
*> classes
;
49 std::map
<int, std::function
<void(std::string
, class_base
*)>> callbacks
;
50 std::map
<int, std::function
<void(class_group
*)>> dcallbacks
;
53 typedef stateobject::type
<state
, state_internal
> state_internal_t
;
54 typedef stateobject::type
<function_group
, fgroup_internal
> fgroup_internal_t
;
55 typedef stateobject::type
<class_group
, cgroup_internal
> cgroup_internal_t
;
58 std::unordered_map
<std::type_index
, void*>& class_types()
60 static std::unordered_map
<std::type_index
, void*> x
;
66 char classtable_meta_key
;
71 static int index(state
& L
);
72 static int newindex(state
& L
);
73 static int pairs(state
& L
);
74 static int pairs_next(state
& L
);
75 static int smethods(state
& L
);
76 static int cmethods(state
& L
);
77 static int trampoline(state
& L
);
78 static void check(state
& L
);
81 void class_info::check(state
& L
)
83 L
.pushlightuserdata(&classtable_meta_key
);
84 L
.rawget(LUA_REGISTRYINDEX
);
86 if(!L
.rawequal(-1, -2))
87 throw std::runtime_error("Bad class table");
91 int class_info::index(state
& L
)
95 class_base
* ptr
= ((class_info
*)L
.touserdata(1))->obj
;
96 const char* method
= L
.tostring(2);
98 throw std::runtime_error("Indexing invalid element of class table");
99 if(!strcmp(method
, "_static_methods")) {
100 L
.pushlightuserdata(ptr
);
101 L
.push_trampoline(class_info::smethods
, 1);
103 } else if(!strcmp(method
, "_class_methods")) {
104 L
.pushlightuserdata(ptr
);
105 L
.push_trampoline(class_info::cmethods
, 1);
108 auto m
= ptr
->static_methods();
110 if(!strcmp(i
.name
, method
)) {
112 std::string fname
= ptr
->get_name() + "::" + i
.name
;
113 L
.pushlightuserdata((void*)i
.fn
);
114 L
.pushstring(fname
.c_str());
115 L
.push_trampoline(class_info::trampoline
, 2);
119 std::string err
= std::string("Class '") + ptr
->get_name() +
120 "' does not have static method '" + method
+ "'";
121 throw std::runtime_error(err
);
123 return 0; //NOTREACHED
125 int class_info::newindex(state
& L
)
127 throw std::runtime_error("Writing into class table not allowed");
130 int class_info::pairs(state
& L
)
134 L
.push_trampoline(class_info::pairs_next
, 0); //Next.
135 L
.pushvalue(1); //State.
136 L
.pushnil(); //Index.
140 int class_info::pairs_next(state
& L
)
144 class_base
* obj
= ((class_info
*)L
.touserdata(1))->obj
;
145 auto m
= obj
->static_methods();
146 std::string key
= (L
.type(2) == LUA_TSTRING
) ? L
.tostring(2) : "";
147 std::string lowbound
= "\xFF"; //Sorts greater than anything that is valid UTF-8.
148 void* best_fn
= NULL
;
150 if(lowbound
> i
.name
&& i
.name
> key
) {
152 best_fn
= (void*)i
.fn
;
155 L
.pushlstring(lowbound
);
156 std::string name
= obj
->get_name() + "::" + lowbound
;
157 L
.pushlightuserdata(best_fn
);
159 L
.push_trampoline(class_info::trampoline
, 2);
167 int class_info::smethods(state
& L
)
169 class_base
* obj
= (class_base
*)L
.touserdata(L
.trampoline_upval(1));
170 auto m
= obj
->static_methods();
173 L
.pushstring(i
.name
);
179 int class_info::cmethods(state
& L
)
181 class_base
* obj
= (class_base
*)L
.touserdata(L
.trampoline_upval(1));
182 auto m
= obj
->class_methods();
185 L
.pushstring(i
.c_str());
191 typedef int (*fn_t
)(state
& L
, parameters
& P
);
192 typedef int (*fnraw_t
)(state
& L
);
195 //1) Pointer to function control block.
196 //2) Pointer to method name.
197 int class_info::trampoline(state
& L
)
199 void* _fn
= L
.touserdata(L
.trampoline_upval(1));
201 std::string name
= L
.tostring(L
.trampoline_upval(2));
202 parameters
P(L
, name
);
207 //1) Pointer to function control block.
208 int lua_trampoline_function(state
& L
)
210 void* ptr
= L
.touserdata(L
.trampoline_upval(1));
211 function
* f
= reinterpret_cast<function
*>(ptr
);
216 //1) Pointer to master state.
217 //2) Poiinter to function to call.
218 int lua_main_trampoline(lua_State
* L
)
220 state
* lstate
= reinterpret_cast<state
*>(lua_touserdata(L
, lua_upvalueindex(1)));
221 void* _fn
= lua_touserdata(L
, lua_upvalueindex(2));
222 fnraw_t fn
= (fnraw_t
)_fn
;
223 //The function is always run in non-set_interruptable mode.
225 state
_L(*lstate
, L
);
226 lstate
->set_interruptable_flag(false);
228 lstate
->set_interruptable_flag(true);
230 } catch(std::exception
& e
) {
231 lua_pushfstring(L
, "%s", e
.what());
232 lstate
->set_interruptable_flag(true);
238 //Pushes given table to top of stack, creating if needed.
239 void recursive_lookup_table(state
& L
, const std::string
& tab
)
243 assert(L
.type(-1) == LUA_TTABLE
);
247 size_t split
= u
.find_last_of(".");
250 if(split
< u
.length()) {
251 u1
= u
.substr(0, split
);
252 u2
= u
.substr(split
+ 1);
254 recursive_lookup_table(L
, u1
);
255 L
.getfield(-1, u2
.c_str());
256 if(L
.type(-1) != LUA_TTABLE
) {
257 //Not a table, create a table.
260 L
.setfield(-2, u2
.c_str());
261 L
.getfield(-1, u2
.c_str());
263 //Get rid of previous table.
268 void register_function(state
& L
, const std::string
& name
, function
* fun
)
270 std::string u
= name
;
271 size_t split
= u
.find_last_of(".");
274 if(split
< u
.length()) {
275 u1
= u
.substr(0, split
);
276 u2
= u
.substr(split
+ 1);
278 recursive_lookup_table(L
, u1
);
282 void* ptr
= reinterpret_cast<void*>(fun
);
283 L
.pushlightuserdata(ptr
);
284 L
.push_trampoline(lua_trampoline_function
, 1);
286 L
.setfield(-2, u2
.c_str());
290 void register_class(state
& L
, const std::string
& name
, class_base
* fun
)
292 fun
->register_state(L
);
295 int run_interruptable_trampoline(lua_State
* L
)
297 //Be very careful with faults here! We are running in interruptable context.
298 static std::string err
;
299 auto& fn
= *(std::function
<void()>*)lua_touserdata(L
, -1);
300 int out
= lua_tonumber(L
, -2);
301 lua_pop(L
, 2); //fn is passed as a pointer, so popping it is OK.
304 } catch(std::exception
& e
) {
306 //This can fault, so err is static.
307 lua_pushlstring(L
, err
.c_str(), err
.length());
314 state::state() throw(std::bad_alloc
)
318 oom_handler
= builtin_oom
;
319 soft_oom_handler
= builtin_soft_oom
;
320 interruptable
= false; //Assume initially not interruptable.
321 memory_limit
= (size_t)-1; //Unlimited.
325 state::state(state
& _master
, lua_State
* L
)
331 state::~state() throw()
335 threads::arlock
h(get_lua_lock());
336 auto state
= state_internal_t::get_soft(this);
338 for(auto i
: state
->function_groups
)
339 i
.first
->drop_callback(i
.second
);
340 for(auto i
: state
->class_groups
)
341 i
.first
->drop_callback(i
.second
);
343 lua_close(lua_handle
);
344 state_internal_t::clear(this);
347 void state::builtin_oom()
349 std::cerr
<< "PANIC: FATAL: Out of memory" << std::endl
;
353 void state::builtin_soft_oom(int status
)
356 std::cerr
<< "Lua: Memory limit exceeded, attempting to free memory..." << std::endl
;
358 std::cerr
<< "Lua: Memory allocation still failed." << std::endl
;
360 std::cerr
<< "Lua: Allocation successful after freeing some memory." << std::endl
;
363 void* state::builtin_alloc(void* user
, void* old
, size_t olds
, size_t news
)
366 auto& st
= *reinterpret_cast<state
*>(user
);
368 if(news
> olds
&& !st
.charge_memory(news
- olds
, false)) {
369 goto retry_allocation
;
371 m
= realloc(old
, news
);
372 if(!m
&& !st
.get_interruptable_flag())
375 st
.charge_memory(news
- olds
, true); //Undo commit.
376 goto retry_allocation
;
379 st
.charge_memory(olds
- news
, true); //Release memory.
380 if(m
&& st
.memory_change
) st
.memory_change((ssize_t
)news
- (ssize_t
)olds
);
383 st
.charge_memory(olds
, true); //Release memory.
384 if(st
.memory_change
) st
.memory_change(-(ssize_t
)olds
);
389 st
.soft_oom_handler(0);
390 st
.interruptable
= false; //Give everything we got for the GC.
391 lua_gc(st
.lua_handle
, LUA_GCCOLLECT
,0); //Do full cycle to try to free some memory.
392 st
.interruptable
= true;
393 if(!st
.charge_memory(news
- olds
, false)) { //Try to see if memory can be allocated.
394 st
.soft_oom_handler(-1);
397 m
= realloc(old
, news
);
398 if(!m
&& news
> olds
)
399 st
.charge_memory(news
- olds
, true); //Undo commit.
400 st
.soft_oom_handler(m
? 1 : -1);
401 if(m
&& st
.memory_change
) st
.memory_change((ssize_t
)news
- (ssize_t
)olds
);
405 void state::push_trampoline(int(*fn
)(state
& L
), unsigned n_upvals
)
407 lua_pushlightuserdata(lua_handle
, (void*)&get_master());
408 lua_pushlightuserdata(lua_handle
, (void*)fn
);
410 lua_insert(lua_handle
, -(int)n_upvals
- 2);
411 lua_insert(lua_handle
, -(int)n_upvals
- 2);
413 lua_pushcclosure(lua_handle
, lua_main_trampoline
, trampoline_upvals
+ n_upvals
);
416 //Lua 5.1 doesn't define LUA_OK.
421 void state::run_interruptable(std::function
<void()> fn
, unsigned in
, unsigned out
)
424 pushlightuserdata(&fn
);
425 pushcfunction(run_interruptable_trampoline
);
426 insert(-(int)in
- 3);
427 int r
= pcall(in
+ 2, out
, 0);
430 } else if(r
== LUA_ERRRUN
) {
431 throw std::runtime_error(tostring(-1));
432 } else if(r
== LUA_ERRMEM
) {
433 throw std::runtime_error("Lua out of memory");
434 } else if(r
== LUA_ERRERR
) {
435 throw std::runtime_error("Lua double fault");
437 } else if(r
== LUA_ERRGCMM
) {
438 throw std::runtime_error("Lua fault in garbage collector");
443 bool state::charge_memory(size_t amount
, bool release
)
445 if(master
) return master
->charge_memory(amount
, release
);
447 if(memory_use
> amount
)
448 memory_use
-= amount
;
454 //Give everything we got.
455 memory_use
+= amount
;
458 //Check limit and refuse allocations too large.
459 if(memory_use
+ amount
> memory_limit
|| memory_use
+ amount
< amount
)
461 memory_use
+= amount
;
466 function::function(function_group
& _group
, const std::string
& func
) throw(std::bad_alloc
)
469 group
.do_register(fname
= func
, *this);
472 function::~function() throw()
474 group
.do_unregister(fname
, *this);
477 class_base::class_base(class_group
& _group
, const std::string
& _name
)
478 : group(_group
), name(_name
)
483 class_base::~class_base() throw()
486 group
.do_unregister(name
, *this);
489 void state::reset() throw(std::bad_alloc
, std::runtime_error
)
492 return master
->reset();
493 threads::arlock
h(get_lua_lock());
494 auto state
= &state_internal_t::get(this);
496 lua_State
* tmp
= lua_newstate(state::builtin_alloc
, this);
498 throw std::runtime_error("Can't re-initialize Lua interpretter");
499 lua_close(lua_handle
);
500 for(auto& i
: state
->callbacks
)
505 lua_handle
= lua_newstate(state::builtin_alloc
, this);
507 throw std::runtime_error("Can't initialize Lua interpretter");
509 for(auto i
: state
->function_groups
)
510 i
.first
->request_callback([this](std::string name
, function
* func
) -> void {
511 register_function(*this, name
, func
);
513 for(auto i
: state
->class_groups
)
514 i
.first
->request_callback([this](std::string name
, class_base
* clazz
) -> void {
515 register_class(*this, name
, clazz
);
519 void state::deinit() throw()
522 return master
->deinit();
524 lua_close(lua_handle
);
528 void state::add_function_group(function_group
& group
)
530 threads::arlock
h(get_lua_lock());
531 auto& state
= state_internal_t::get(this);
532 state
.function_groups
.insert(std::make_pair(&group
, group
.add_callback([this](const std::string
& name
,
533 function
* func
) -> void {
534 this->function_callback(name
, func
);
535 }, [this](function_group
* x
) {
536 threads::arlock
h(get_lua_lock());
537 auto state
= state_internal_t::get_soft(this);
539 for(auto i
= state
->function_groups
.begin(); i
!= state
->function_groups
.end();)
541 i
= state
->function_groups
.erase(i
);
547 void state::add_class_group(class_group
& group
)
549 threads::arlock
h(get_lua_lock());
550 auto& state
= state_internal_t::get(this);
551 state
.class_groups
.insert(std::make_pair(&group
, group
.add_callback([this](const std::string
& name
,
552 class_base
* clazz
) -> void {
553 this->class_callback(name
, clazz
);
554 }, [this](class_group
* x
) {
555 threads::arlock
h(get_lua_lock());
556 auto state
= state_internal_t::get_soft(this);
558 for(auto i
= state
->class_groups
.begin(); i
!= state
->class_groups
.end();)
560 i
= state
->class_groups
.erase(i
);
566 void state::function_callback(const std::string
& name
, function
* func
)
569 return master
->function_callback(name
, func
);
571 register_function(*this, name
, func
);
574 void state::class_callback(const std::string
& name
, class_base
* clazz
)
577 return master
->class_callback(name
, clazz
);
579 register_class(*this, name
, clazz
);
582 bool state::do_once(void* key
)
585 return master
->do_once(key
);
586 pushlightuserdata(key
);
587 rawget(LUA_REGISTRYINDEX
);
588 if(type(-1) == LUA_TNIL
) {
590 pushlightuserdata(key
);
591 pushlightuserdata(key
);
592 rawset(LUA_REGISTRYINDEX
);
600 std::list
<state::callback_list
*> state::get_callbacks()
603 return master
->get_callbacks();
604 threads::arlock
h(get_lua_lock());
605 auto state
= state_internal_t::get_soft(this);
606 std::list
<callback_list
*> r
;
608 for(auto i
: state
->callbacks
)
609 r
.push_back(i
.second
);
613 void state::do_register(const std::string
& name
, callback_list
& callback
)
615 threads::arlock
h(get_lua_lock());
616 auto& state
= state_internal_t::get(this);
617 if(state
.callbacks
.count(name
)) return;
618 state
.callbacks
[name
] = &callback
;
621 void state::do_unregister(const std::string
& name
, callback_list
& callback
)
623 threads::arlock
h(get_lua_lock());
624 auto state
= state_internal_t::get_soft(this);
625 if(state
&& state
->callbacks
.count(name
) && state
->callbacks
[name
] == &callback
)
626 state
->callbacks
.erase(name
);
629 state::callback_list::callback_list(state
& _L
, const std::string
& _name
, const std::string
& fncbname
)
630 : L(_L
), name(_name
), fn_cbname(fncbname
)
632 L
.do_register(name
, *this);
635 state::callback_list::~callback_list()
637 L
.do_unregister(name
, *this);
640 for(auto& i
: callbacks
) {
641 L
.pushlightuserdata(&i
);
643 L
.rawset(LUA_REGISTRYINDEX
);
647 void state::callback_list::_register(state
& _L
)
649 callbacks
.push_back(0);
650 _L
.pushlightuserdata(&*callbacks
.rbegin());
652 _L
.rawset(LUA_REGISTRYINDEX
);
655 void state::callback_list::_unregister(state
& _L
)
657 for(auto i
= callbacks
.begin(); i
!= callbacks
.end();) {
658 _L
.pushlightuserdata(&*i
);
659 _L
.rawget(LUA_REGISTRYINDEX
);
660 if(_L
.rawequal(-1, -2)) {
662 _L
.pushlightuserdata(key
);
664 _L
.rawset(LUA_REGISTRYINDEX
);
665 i
= callbacks
.erase(i
);
672 function_group::function_group()
676 function_group::~function_group()
678 threads::arlock
h(get_lua_lock());
679 auto state
= fgroup_internal_t::get_soft(this);
681 for(auto i
: state
->dcallbacks
)
683 fgroup_internal_t::clear(this);
686 void function_group::request_callback(std::function
<void(std::string
, function
*)> cb
)
688 threads::arlock
h(get_lua_lock());
689 auto state
= fgroup_internal_t::get_soft(this);
691 for(auto i
: state
->functions
)
692 cb(i
.first
, i
.second
);
695 int function_group::add_callback(std::function
<void(std::string
, function
*)> cb
,
696 std::function
<void(function_group
*)> dcb
)
698 threads::arlock
h(get_lua_lock());
699 auto& state
= fgroup_internal_t::get(this);
700 int handle
= state
.next_handle
++;
701 state
.callbacks
[handle
] = cb
;
702 state
.dcallbacks
[handle
] = dcb
;
703 for(auto i
: state
.functions
)
704 cb(i
.first
, i
.second
);
708 void function_group::drop_callback(int handle
)
710 threads::arlock
h(get_lua_lock());
711 auto state
= fgroup_internal_t::get_soft(this);
713 state
->callbacks
.erase(handle
);
716 void function_group::do_register(const std::string
& name
, function
& fun
)
718 threads::arlock
h(get_lua_lock());
719 auto& state
= fgroup_internal_t::get(this);
720 if(state
.functions
.count(name
)) return;
721 state
.functions
[name
] = &fun
;
722 for(auto i
: state
.callbacks
)
723 i
.second(name
, &fun
);
726 void function_group::do_unregister(const std::string
& name
, function
& fun
)
728 threads::arlock
h(get_lua_lock());
729 auto state
= fgroup_internal_t::get_soft(this);
730 if(!state
|| !state
->functions
.count(name
) || state
->functions
[name
] != &fun
) return;
731 state
->functions
.erase(name
);
732 for(auto i
: state
->callbacks
)
733 i
.second(name
, NULL
);
736 class_group::class_group()
740 class_group::~class_group()
742 threads::arlock
h(get_lua_lock());
743 auto state
= cgroup_internal_t::get_soft(this);
745 for(auto i
: state
->dcallbacks
)
747 cgroup_internal_t::clear(this);
750 void class_group::request_callback(std::function
<void(std::string
, class_base
*)> cb
)
752 threads::arlock
h(get_lua_lock());
753 auto state
= cgroup_internal_t::get_soft(this);
755 for(auto i
: state
->classes
)
756 cb(i
.first
, i
.second
);
759 int class_group::add_callback(std::function
<void(std::string
, class_base
*)> cb
,
760 std::function
<void(class_group
*)> dcb
)
762 threads::arlock
h(get_lua_lock());
763 auto& state
= cgroup_internal_t::get(this);
764 int handle
= state
.next_handle
++;
765 state
.callbacks
[handle
] = cb
;
766 state
.dcallbacks
[handle
] = dcb
;
767 for(auto i
: state
.classes
)
768 cb(i
.first
, i
.second
);
772 void class_group::drop_callback(int handle
)
774 threads::arlock
h(get_lua_lock());
775 auto state
= cgroup_internal_t::get_soft(this);
777 state
->callbacks
.erase(handle
);
780 void class_group::do_register(const std::string
& name
, class_base
& fun
)
782 threads::arlock
h(get_lua_lock());
783 auto& state
= cgroup_internal_t::get(this);
784 if(state
.classes
.count(name
)) return;
785 state
.classes
[name
] = &fun
;
786 for(auto i
: state
.callbacks
)
787 i
.second(name
, &fun
);
790 void class_group::do_unregister(const std::string
& name
, class_base
& fun
)
792 threads::arlock
h(get_lua_lock());
793 auto state
= cgroup_internal_t::get_soft(this);
794 if(!state
|| !state
->classes
.count(name
) || state
->classes
[name
] != &fun
) return;
795 state
->classes
.erase(name
);
796 for(auto i
: state
->callbacks
)
797 i
.second(name
, NULL
);
800 std::list
<class_ops
>& userdata_recogn_fns()
802 static std::list
<class_ops
> x
;
806 std::string
try_recognize_userdata(state
& state
, int index
)
808 for(auto i
: userdata_recogn_fns())
809 if(i
.is(state
, index
))
811 //Hack: Lua builtin file objects and classobjs.
812 if(state
.getmetatable(index
)) {
813 state
.pushstring("FILE*");
814 state
.rawget(LUA_REGISTRYINDEX
);
815 if(state
.rawequal(-1, -2)) {
820 state
.pushlightuserdata(&classtable_meta_key
);
821 state
.rawget(LUA_REGISTRYINDEX
);
822 if(state
.rawequal(-1, -2)) {
831 std::string
try_print_userdata(state
& L
, int index
)
833 for(auto i
: userdata_recogn_fns())
835 return i
.print(L
, index
);
837 if(L
.getmetatable(index
)) {
838 L
.pushlightuserdata(&classtable_meta_key
);
839 L
.rawget(LUA_REGISTRYINDEX
);
840 if(L
.rawequal(-1, -2)) {
842 std::string cname
= ((class_info
*)L
.touserdata(index
))->obj
->get_name();
847 return "no data available";
850 int state::vararg_tag::pushargs(state
& L
)
858 else if(i
== "false")
859 L
.pushboolean(false);
860 else if(regex_match("[+-]?(|0|[1-9][0-9]*)(.[0-9]+)?([eE][+-]?(0|[1-9][0-9]*))?", i
))
861 L
.pushnumber(strtod(i
.c_str(), NULL
));
863 L
.pushlstring(i
.substr(1));
871 class_base
* class_base::lookup(state
& L
, const std::string
& _name
)
873 if(lookup_and_push(L
, _name
)) {
874 class_base
* obj
= ((class_info
*)L
.touserdata(-1))->obj
;
881 bool class_base::lookup_and_push(state
& L
, const std::string
& _name
)
883 L
.pushlightuserdata(&classtable_key
);
884 L
.rawget(LUA_REGISTRYINDEX
);
885 if(L
.type(-1) == LUA_TNIL
) {
890 //On top of stack there is class table.
891 L
.pushlstring(_name
);
893 if(L
.type(-1) == LUA_TNIL
) {
903 std::set
<std::string
> class_base::all_classes(state
& L
)
905 L
.pushlightuserdata(&classtable_key
);
906 L
.rawget(LUA_REGISTRYINDEX
);
907 if(L
.type(-1) == LUA_TNIL
) {
910 return std::set
<std::string
>();
912 std::set
<std::string
> r
;
915 L
.pop(1); //Pop value.
916 if(L
.type(-1) == LUA_TSTRING
) r
.insert(L
.tostring(-1));
922 void class_base::register_static(state
& L
)
925 L
.pushlightuserdata(&classtable_key
);
926 L
.rawget(LUA_REGISTRYINDEX
);
927 if(L
.type(-1) == LUA_TNIL
) {
929 L
.pushlightuserdata(&classtable_key
);
931 L
.rawset(LUA_REGISTRYINDEX
);
934 //On top of stack there is class table.
937 if(L
.type(-1) != LUA_TNIL
) {
938 //Already registered.
944 //Now construct the object.
945 class_info
* ci
= (class_info
*)L
.newuserdata(sizeof(class_info
));
948 L
.pushlightuserdata(&classtable_meta_key
);
949 L
.rawget(LUA_REGISTRYINDEX
);
950 if(L
.type(-1) == LUA_TNIL
) {
952 L
.pushlightuserdata(&classtable_meta_key
);
954 L
.pushstring("__index");
955 L
.push_trampoline(class_info::index
, 0);
957 L
.pushstring("__newindex");
958 L
.push_trampoline(class_info::newindex
, 0);
960 L
.pushstring("__pairs");
961 L
.push_trampoline(class_info::pairs
, 0);
963 L
.rawset(LUA_REGISTRYINDEX
);
971 void class_base::delayed_register()
973 group
.do_register(name
, *this);
976 functions::functions(function_group
& grp
, const std::string
& basetable
, std::initializer_list
<entry
> fnlist
)
978 std::string base
= (basetable
== "") ? "" : (basetable
+ ".");
980 funcs
.insert(new fn(grp
, base
+ i
.name
, i
.func
));
983 functions::~functions()
989 functions::fn::fn(function_group
& grp
, const std::string
& name
, std::function
<int(state
& L
, parameters
& P
)> _func
)
990 : function(grp
, name
)
995 functions::fn::~fn() throw()
999 int functions::fn::invoke(state
& L
)
1001 lua::parameters
P(L
, fname
);