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());
315 state::state() throw(std::bad_alloc
)
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
) throw(std::bad_alloc
)
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);
490 void state::reset() throw(std::bad_alloc
, std::runtime_error
)
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
)
633 L
.do_register(name
, *this);
636 state::callback_list::~callback_list()
638 L
.do_unregister(name
, *this);
641 for(auto& i
: callbacks
) {
642 L
.pushlightuserdata(&i
);
644 L
.rawset(LUA_REGISTRYINDEX
);
648 void state::callback_list::_register(state
& _L
)
650 callbacks
.push_back(0);
651 _L
.pushlightuserdata(&*callbacks
.rbegin());
653 _L
.rawset(LUA_REGISTRYINDEX
);
656 void state::callback_list::_unregister(state
& _L
)
658 for(auto i
= callbacks
.begin(); i
!= callbacks
.end();) {
659 _L
.pushlightuserdata(&*i
);
660 _L
.rawget(LUA_REGISTRYINDEX
);
661 if(_L
.rawequal(-1, -2)) {
663 _L
.pushlightuserdata(key
);
665 _L
.rawset(LUA_REGISTRYINDEX
);
666 i
= callbacks
.erase(i
);
673 function_group::function_group()
677 function_group::~function_group()
679 threads::arlock
h(get_lua_lock());
680 auto state
= fgroup_internal_t::get_soft(this);
682 for(auto i
: state
->dcallbacks
)
684 fgroup_internal_t::clear(this);
687 void function_group::request_callback(std::function
<void(std::string
, function
*)> cb
)
689 threads::arlock
h(get_lua_lock());
690 auto state
= fgroup_internal_t::get_soft(this);
692 for(auto i
: state
->functions
)
693 cb(i
.first
, i
.second
);
696 int function_group::add_callback(std::function
<void(std::string
, function
*)> cb
,
697 std::function
<void(function_group
*)> dcb
)
699 threads::arlock
h(get_lua_lock());
700 auto& state
= fgroup_internal_t::get(this);
701 int handle
= state
.next_handle
++;
702 state
.callbacks
[handle
] = cb
;
703 state
.dcallbacks
[handle
] = dcb
;
704 for(auto i
: state
.functions
)
705 cb(i
.first
, i
.second
);
709 void function_group::drop_callback(int handle
)
711 threads::arlock
h(get_lua_lock());
712 auto state
= fgroup_internal_t::get_soft(this);
714 state
->callbacks
.erase(handle
);
717 void function_group::do_register(const std::string
& name
, function
& fun
)
719 threads::arlock
h(get_lua_lock());
720 auto& state
= fgroup_internal_t::get(this);
721 if(state
.functions
.count(name
)) return;
722 state
.functions
[name
] = &fun
;
723 for(auto i
: state
.callbacks
)
724 i
.second(name
, &fun
);
727 void function_group::do_unregister(const std::string
& name
, function
& fun
)
729 threads::arlock
h(get_lua_lock());
730 auto state
= fgroup_internal_t::get_soft(this);
731 if(!state
|| !state
->functions
.count(name
) || state
->functions
[name
] != &fun
) return;
732 state
->functions
.erase(name
);
733 for(auto i
: state
->callbacks
)
734 i
.second(name
, NULL
);
737 class_group::class_group()
741 class_group::~class_group()
743 threads::arlock
h(get_lua_lock());
744 auto state
= cgroup_internal_t::get_soft(this);
746 for(auto i
: state
->dcallbacks
)
748 cgroup_internal_t::clear(this);
751 void class_group::request_callback(std::function
<void(std::string
, class_base
*)> cb
)
753 threads::arlock
h(get_lua_lock());
754 auto state
= cgroup_internal_t::get_soft(this);
756 for(auto i
: state
->classes
)
757 cb(i
.first
, i
.second
);
760 int class_group::add_callback(std::function
<void(std::string
, class_base
*)> cb
,
761 std::function
<void(class_group
*)> dcb
)
763 threads::arlock
h(get_lua_lock());
764 auto& state
= cgroup_internal_t::get(this);
765 int handle
= state
.next_handle
++;
766 state
.callbacks
[handle
] = cb
;
767 state
.dcallbacks
[handle
] = dcb
;
768 for(auto i
: state
.classes
)
769 cb(i
.first
, i
.second
);
773 void class_group::drop_callback(int handle
)
775 threads::arlock
h(get_lua_lock());
776 auto state
= cgroup_internal_t::get_soft(this);
778 state
->callbacks
.erase(handle
);
781 void class_group::do_register(const std::string
& name
, class_base
& fun
)
783 threads::arlock
h(get_lua_lock());
784 auto& state
= cgroup_internal_t::get(this);
785 if(state
.classes
.count(name
)) return;
786 state
.classes
[name
] = &fun
;
787 for(auto i
: state
.callbacks
)
788 i
.second(name
, &fun
);
791 void class_group::do_unregister(const std::string
& name
, class_base
& fun
)
793 threads::arlock
h(get_lua_lock());
794 auto state
= cgroup_internal_t::get_soft(this);
795 if(!state
|| !state
->classes
.count(name
) || state
->classes
[name
] != &fun
) return;
796 state
->classes
.erase(name
);
797 for(auto i
: state
->callbacks
)
798 i
.second(name
, NULL
);
801 std::list
<class_ops
>& userdata_recogn_fns()
803 static std::list
<class_ops
> x
;
807 std::string
try_recognize_userdata(state
& state
, int index
)
809 for(auto i
: userdata_recogn_fns())
810 if(i
.is(state
, index
))
812 //Hack: Lua builtin file objects and classobjs.
813 if(state
.getmetatable(index
)) {
814 state
.pushstring("FILE*");
815 state
.rawget(LUA_REGISTRYINDEX
);
816 if(state
.rawequal(-1, -2)) {
821 state
.pushlightuserdata(&classtable_meta_key
);
822 state
.rawget(LUA_REGISTRYINDEX
);
823 if(state
.rawequal(-1, -2)) {
832 std::string
try_print_userdata(state
& L
, int index
)
834 for(auto i
: userdata_recogn_fns())
836 return i
.print(L
, index
);
838 if(L
.getmetatable(index
)) {
839 L
.pushlightuserdata(&classtable_meta_key
);
840 L
.rawget(LUA_REGISTRYINDEX
);
841 if(L
.rawequal(-1, -2)) {
843 std::string cname
= ((class_info
*)L
.touserdata(index
))->obj
->get_name();
848 return "no data available";
851 int state::vararg_tag::pushargs(state
& L
)
859 else if(i
== "false")
860 L
.pushboolean(false);
861 else if(regex_match("[+-]?(|0|[1-9][0-9]*)(.[0-9]+)?([eE][+-]?(0|[1-9][0-9]*))?", i
))
862 L
.pushnumber(strtod(i
.c_str(), NULL
));
864 L
.pushlstring(i
.substr(1));
872 class_base
* class_base::lookup(state
& L
, const std::string
& _name
)
874 if(lookup_and_push(L
, _name
)) {
875 class_base
* obj
= ((class_info
*)L
.touserdata(-1))->obj
;
882 bool class_base::lookup_and_push(state
& L
, const std::string
& _name
)
884 L
.pushlightuserdata(&classtable_key
);
885 L
.rawget(LUA_REGISTRYINDEX
);
886 if(L
.type(-1) == LUA_TNIL
) {
891 //On top of stack there is class table.
892 L
.pushlstring(_name
);
894 if(L
.type(-1) == LUA_TNIL
) {
904 std::set
<std::string
> class_base::all_classes(state
& L
)
906 L
.pushlightuserdata(&classtable_key
);
907 L
.rawget(LUA_REGISTRYINDEX
);
908 if(L
.type(-1) == LUA_TNIL
) {
911 return std::set
<std::string
>();
913 std::set
<std::string
> r
;
916 L
.pop(1); //Pop value.
917 if(L
.type(-1) == LUA_TSTRING
) r
.insert(L
.tostring(-1));
923 void class_base::register_static(state
& L
)
926 L
.pushlightuserdata(&classtable_key
);
927 L
.rawget(LUA_REGISTRYINDEX
);
928 if(L
.type(-1) == LUA_TNIL
) {
930 L
.pushlightuserdata(&classtable_key
);
932 L
.rawset(LUA_REGISTRYINDEX
);
935 //On top of stack there is class table.
938 if(L
.type(-1) != LUA_TNIL
) {
939 //Already registered.
945 //Now construct the object.
946 class_info
* ci
= (class_info
*)L
.newuserdata(sizeof(class_info
));
949 L
.pushlightuserdata(&classtable_meta_key
);
950 L
.rawget(LUA_REGISTRYINDEX
);
951 if(L
.type(-1) == LUA_TNIL
) {
953 L
.pushlightuserdata(&classtable_meta_key
);
955 L
.pushstring("__index");
956 L
.push_trampoline(class_info::index
, 0);
958 L
.pushstring("__newindex");
959 L
.push_trampoline(class_info::newindex
, 0);
961 L
.pushstring("__pairs");
962 L
.push_trampoline(class_info::pairs
, 0);
964 L
.rawset(LUA_REGISTRYINDEX
);
972 void class_base::delayed_register()
974 group
.do_register(name
, *this);
977 functions::functions(function_group
& grp
, const std::string
& basetable
, std::initializer_list
<entry
> fnlist
)
979 std::string base
= (basetable
== "") ? "" : (basetable
+ ".");
981 funcs
.insert(new fn(grp
, base
+ i
.name
, i
.func
));
984 functions::~functions()
990 functions::fn::fn(function_group
& grp
, const std::string
& name
, std::function
<int(state
& L
, parameters
& P
)> _func
)
991 : function(grp
, name
)
996 functions::fn::~fn() throw()
1000 int functions::fn::invoke(state
& L
)
1002 lua::parameters
P(L
, fname
);