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 void state::run_interruptable(std::function
<void()> fn
, unsigned in
, unsigned out
)
419 pushlightuserdata(&fn
);
420 pushcfunction(run_interruptable_trampoline
);
421 insert(-(int)in
- 3);
422 int r
= pcall(in
+ 2, out
, 0);
425 } else if(r
== LUA_ERRRUN
) {
426 throw std::runtime_error(tostring(-1));
427 } else if(r
== LUA_ERRMEM
) {
428 throw std::runtime_error("Lua out of memory");
429 } else if(r
== LUA_ERRERR
) {
430 throw std::runtime_error("Lua double fault");
432 } else if(r
== LUA_ERRGCMM
) {
433 throw std::runtime_error("Lua fault in garbage collector");
438 bool state::charge_memory(size_t amount
, bool release
)
440 if(master
) return master
->charge_memory(amount
, release
);
442 if(memory_use
> amount
)
443 memory_use
-= amount
;
449 //Give everything we got.
450 memory_use
+= amount
;
453 //Check limit and refuse allocations too large.
454 if(memory_use
+ amount
> memory_limit
|| memory_use
+ amount
< amount
)
456 memory_use
+= amount
;
461 function::function(function_group
& _group
, const std::string
& func
) throw(std::bad_alloc
)
464 group
.do_register(fname
= func
, *this);
467 function::~function() throw()
469 group
.do_unregister(fname
, *this);
472 class_base::class_base(class_group
& _group
, const std::string
& _name
)
473 : group(_group
), name(_name
)
478 class_base::~class_base() throw()
481 group
.do_unregister(name
, *this);
484 void state::reset() throw(std::bad_alloc
, std::runtime_error
)
487 return master
->reset();
488 threads::arlock
h(get_lua_lock());
489 auto state
= &state_internal_t::get(this);
491 lua_State
* tmp
= lua_newstate(state::builtin_alloc
, this);
493 throw std::runtime_error("Can't re-initialize Lua interpretter");
494 lua_close(lua_handle
);
495 for(auto& i
: state
->callbacks
)
500 lua_handle
= lua_newstate(state::builtin_alloc
, this);
502 throw std::runtime_error("Can't initialize Lua interpretter");
504 for(auto i
: state
->function_groups
)
505 i
.first
->request_callback([this](std::string name
, function
* func
) -> void {
506 register_function(*this, name
, func
);
508 for(auto i
: state
->class_groups
)
509 i
.first
->request_callback([this](std::string name
, class_base
* clazz
) -> void {
510 register_class(*this, name
, clazz
);
514 void state::deinit() throw()
517 return master
->deinit();
519 lua_close(lua_handle
);
523 void state::add_function_group(function_group
& group
)
525 threads::arlock
h(get_lua_lock());
526 auto& state
= state_internal_t::get(this);
527 state
.function_groups
.insert(std::make_pair(&group
, group
.add_callback([this](const std::string
& name
,
528 function
* func
) -> void {
529 this->function_callback(name
, func
);
530 }, [this](function_group
* x
) {
531 threads::arlock
h(get_lua_lock());
532 auto state
= state_internal_t::get_soft(this);
534 for(auto i
= state
->function_groups
.begin(); i
!= state
->function_groups
.end();)
536 i
= state
->function_groups
.erase(i
);
542 void state::add_class_group(class_group
& group
)
544 threads::arlock
h(get_lua_lock());
545 auto& state
= state_internal_t::get(this);
546 state
.class_groups
.insert(std::make_pair(&group
, group
.add_callback([this](const std::string
& name
,
547 class_base
* clazz
) -> void {
548 this->class_callback(name
, clazz
);
549 }, [this](class_group
* x
) {
550 threads::arlock
h(get_lua_lock());
551 auto state
= state_internal_t::get_soft(this);
553 for(auto i
= state
->class_groups
.begin(); i
!= state
->class_groups
.end();)
555 i
= state
->class_groups
.erase(i
);
561 void state::function_callback(const std::string
& name
, function
* func
)
564 return master
->function_callback(name
, func
);
566 register_function(*this, name
, func
);
569 void state::class_callback(const std::string
& name
, class_base
* clazz
)
572 return master
->class_callback(name
, clazz
);
574 register_class(*this, name
, clazz
);
577 bool state::do_once(void* key
)
580 return master
->do_once(key
);
581 pushlightuserdata(key
);
582 rawget(LUA_REGISTRYINDEX
);
583 if(type(-1) == LUA_TNIL
) {
585 pushlightuserdata(key
);
586 pushlightuserdata(key
);
587 rawset(LUA_REGISTRYINDEX
);
595 std::list
<state::callback_list
*> state::get_callbacks()
598 return master
->get_callbacks();
599 threads::arlock
h(get_lua_lock());
600 auto state
= state_internal_t::get_soft(this);
601 std::list
<callback_list
*> r
;
603 for(auto i
: state
->callbacks
)
604 r
.push_back(i
.second
);
608 void state::do_register(const std::string
& name
, callback_list
& callback
)
610 threads::arlock
h(get_lua_lock());
611 auto& state
= state_internal_t::get(this);
612 if(state
.callbacks
.count(name
)) return;
613 state
.callbacks
[name
] = &callback
;
616 void state::do_unregister(const std::string
& name
, callback_list
& callback
)
618 threads::arlock
h(get_lua_lock());
619 auto state
= state_internal_t::get_soft(this);
620 if(state
&& state
->callbacks
.count(name
) && state
->callbacks
[name
] == &callback
)
621 state
->callbacks
.erase(name
);
624 state::callback_list::callback_list(state
& _L
, const std::string
& _name
, const std::string
& fncbname
)
625 : L(_L
), name(_name
), fn_cbname(fncbname
)
627 L
.do_register(name
, *this);
630 state::callback_list::~callback_list()
632 L
.do_unregister(name
, *this);
635 for(auto& i
: callbacks
) {
636 L
.pushlightuserdata(&i
);
638 L
.rawset(LUA_REGISTRYINDEX
);
642 void state::callback_list::_register(state
& _L
)
644 callbacks
.push_back(0);
645 _L
.pushlightuserdata(&*callbacks
.rbegin());
647 _L
.rawset(LUA_REGISTRYINDEX
);
650 void state::callback_list::_unregister(state
& _L
)
652 for(auto i
= callbacks
.begin(); i
!= callbacks
.end();) {
653 _L
.pushlightuserdata(&*i
);
654 _L
.rawget(LUA_REGISTRYINDEX
);
655 if(_L
.rawequal(-1, -2)) {
657 _L
.pushlightuserdata(key
);
659 _L
.rawset(LUA_REGISTRYINDEX
);
660 i
= callbacks
.erase(i
);
667 function_group::function_group()
671 function_group::~function_group()
673 threads::arlock
h(get_lua_lock());
674 auto state
= fgroup_internal_t::get_soft(this);
676 for(auto i
: state
->dcallbacks
)
678 fgroup_internal_t::clear(this);
681 void function_group::request_callback(std::function
<void(std::string
, function
*)> cb
)
683 threads::arlock
h(get_lua_lock());
684 auto state
= fgroup_internal_t::get_soft(this);
686 for(auto i
: state
->functions
)
687 cb(i
.first
, i
.second
);
690 int function_group::add_callback(std::function
<void(std::string
, function
*)> cb
,
691 std::function
<void(function_group
*)> dcb
)
693 threads::arlock
h(get_lua_lock());
694 auto& state
= fgroup_internal_t::get(this);
695 int handle
= state
.next_handle
++;
696 state
.callbacks
[handle
] = cb
;
697 state
.dcallbacks
[handle
] = dcb
;
698 for(auto i
: state
.functions
)
699 cb(i
.first
, i
.second
);
703 void function_group::drop_callback(int handle
)
705 threads::arlock
h(get_lua_lock());
706 auto state
= fgroup_internal_t::get_soft(this);
708 state
->callbacks
.erase(handle
);
711 void function_group::do_register(const std::string
& name
, function
& fun
)
713 threads::arlock
h(get_lua_lock());
714 auto& state
= fgroup_internal_t::get(this);
715 if(state
.functions
.count(name
)) return;
716 state
.functions
[name
] = &fun
;
717 for(auto i
: state
.callbacks
)
718 i
.second(name
, &fun
);
721 void function_group::do_unregister(const std::string
& name
, function
& fun
)
723 threads::arlock
h(get_lua_lock());
724 auto state
= fgroup_internal_t::get_soft(this);
725 if(!state
|| !state
->functions
.count(name
) || state
->functions
[name
] != &fun
) return;
726 state
->functions
.erase(name
);
727 for(auto i
: state
->callbacks
)
728 i
.second(name
, NULL
);
731 class_group::class_group()
735 class_group::~class_group()
737 threads::arlock
h(get_lua_lock());
738 auto state
= cgroup_internal_t::get_soft(this);
740 for(auto i
: state
->dcallbacks
)
742 cgroup_internal_t::clear(this);
745 void class_group::request_callback(std::function
<void(std::string
, class_base
*)> cb
)
747 threads::arlock
h(get_lua_lock());
748 auto state
= cgroup_internal_t::get_soft(this);
750 for(auto i
: state
->classes
)
751 cb(i
.first
, i
.second
);
754 int class_group::add_callback(std::function
<void(std::string
, class_base
*)> cb
,
755 std::function
<void(class_group
*)> dcb
)
757 threads::arlock
h(get_lua_lock());
758 auto& state
= cgroup_internal_t::get(this);
759 int handle
= state
.next_handle
++;
760 state
.callbacks
[handle
] = cb
;
761 state
.dcallbacks
[handle
] = dcb
;
762 for(auto i
: state
.classes
)
763 cb(i
.first
, i
.second
);
767 void class_group::drop_callback(int handle
)
769 threads::arlock
h(get_lua_lock());
770 auto state
= cgroup_internal_t::get_soft(this);
772 state
->callbacks
.erase(handle
);
775 void class_group::do_register(const std::string
& name
, class_base
& fun
)
777 threads::arlock
h(get_lua_lock());
778 auto& state
= cgroup_internal_t::get(this);
779 if(state
.classes
.count(name
)) return;
780 state
.classes
[name
] = &fun
;
781 for(auto i
: state
.callbacks
)
782 i
.second(name
, &fun
);
785 void class_group::do_unregister(const std::string
& name
, class_base
& fun
)
787 threads::arlock
h(get_lua_lock());
788 auto state
= cgroup_internal_t::get_soft(this);
789 if(!state
|| !state
->classes
.count(name
) || state
->classes
[name
] != &fun
) return;
790 state
->classes
.erase(name
);
791 for(auto i
: state
->callbacks
)
792 i
.second(name
, NULL
);
795 std::list
<class_ops
>& userdata_recogn_fns()
797 static std::list
<class_ops
> x
;
801 std::string
try_recognize_userdata(state
& state
, int index
)
803 for(auto i
: userdata_recogn_fns())
804 if(i
.is(state
, index
))
806 //Hack: Lua builtin file objects and classobjs.
807 if(state
.getmetatable(index
)) {
808 state
.pushstring("FILE*");
809 state
.rawget(LUA_REGISTRYINDEX
);
810 if(state
.rawequal(-1, -2)) {
815 state
.pushlightuserdata(&classtable_meta_key
);
816 state
.rawget(LUA_REGISTRYINDEX
);
817 if(state
.rawequal(-1, -2)) {
826 std::string
try_print_userdata(state
& L
, int index
)
828 for(auto i
: userdata_recogn_fns())
830 return i
.print(L
, index
);
832 if(L
.getmetatable(index
)) {
833 L
.pushlightuserdata(&classtable_meta_key
);
834 L
.rawget(LUA_REGISTRYINDEX
);
835 if(L
.rawequal(-1, -2)) {
837 std::string cname
= ((class_info
*)L
.touserdata(index
))->obj
->get_name();
842 return "no data available";
845 int state::vararg_tag::pushargs(state
& L
)
853 else if(i
== "false")
854 L
.pushboolean(false);
855 else if(regex_match("[+-]?(|0|[1-9][0-9]*)(.[0-9]+)?([eE][+-]?(0|[1-9][0-9]*))?", i
))
856 L
.pushnumber(strtod(i
.c_str(), NULL
));
858 L
.pushlstring(i
.substr(1));
866 class_base
* class_base::lookup(state
& L
, const std::string
& _name
)
868 if(lookup_and_push(L
, _name
)) {
869 class_base
* obj
= ((class_info
*)L
.touserdata(-1))->obj
;
876 bool class_base::lookup_and_push(state
& L
, const std::string
& _name
)
878 L
.pushlightuserdata(&classtable_key
);
879 L
.rawget(LUA_REGISTRYINDEX
);
880 if(L
.type(-1) == LUA_TNIL
) {
885 //On top of stack there is class table.
886 L
.pushlstring(_name
);
888 if(L
.type(-1) == LUA_TNIL
) {
898 std::set
<std::string
> class_base::all_classes(state
& L
)
900 L
.pushlightuserdata(&classtable_key
);
901 L
.rawget(LUA_REGISTRYINDEX
);
902 if(L
.type(-1) == LUA_TNIL
) {
905 return std::set
<std::string
>();
907 std::set
<std::string
> r
;
910 L
.pop(1); //Pop value.
911 if(L
.type(-1) == LUA_TSTRING
) r
.insert(L
.tostring(-1));
917 void class_base::register_static(state
& L
)
920 L
.pushlightuserdata(&classtable_key
);
921 L
.rawget(LUA_REGISTRYINDEX
);
922 if(L
.type(-1) == LUA_TNIL
) {
924 L
.pushlightuserdata(&classtable_key
);
926 L
.rawset(LUA_REGISTRYINDEX
);
929 //On top of stack there is class table.
932 if(L
.type(-1) != LUA_TNIL
) {
933 //Already registered.
939 //Now construct the object.
940 class_info
* ci
= (class_info
*)L
.newuserdata(sizeof(class_info
));
943 L
.pushlightuserdata(&classtable_meta_key
);
944 L
.rawget(LUA_REGISTRYINDEX
);
945 if(L
.type(-1) == LUA_TNIL
) {
947 L
.pushlightuserdata(&classtable_meta_key
);
949 L
.pushstring("__index");
950 L
.push_trampoline(class_info::index
, 0);
952 L
.pushstring("__newindex");
953 L
.push_trampoline(class_info::newindex
, 0);
955 L
.pushstring("__pairs");
956 L
.push_trampoline(class_info::pairs
, 0);
958 L
.rawset(LUA_REGISTRYINDEX
);
966 void class_base::delayed_register()
968 group
.do_register(name
, *this);
971 functions::functions(function_group
& grp
, const std::string
& basetable
, std::initializer_list
<entry
> fnlist
)
973 std::string base
= (basetable
== "") ? "" : (basetable
+ ".");
975 funcs
.insert(new fn(grp
, base
+ i
.name
, i
.func
));
978 functions::~functions()
984 functions::fn::fn(function_group
& grp
, const std::string
& name
, std::function
<int(state
& L
, parameters
& P
)> _func
)
985 : function(grp
, name
)
990 functions::fn::~fn() throw()
994 int functions::fn::invoke(state
& L
)
996 lua::parameters
P(L
, fname
);