Get rid of DECLARE_LUACLASS
[lsnes.git] / include / library / luabase.hpp
blob06b40947da526aae6b3564559e11e569fbfb6828
1 #ifndef _library__luabase__hpp__included__
2 #define _library__luabase__hpp__included__
4 #include <string>
5 #include <stdexcept>
6 #include <typeinfo>
7 #include <typeindex>
8 #include <map>
9 #include <unordered_map>
10 #include <set>
11 #include <list>
12 #include <cassert>
13 #include "string.hpp"
14 #include "utf8.hpp"
15 extern "C"
17 #include <lua.h>
20 class lua_state;
22 struct luaclass_methods
24 bool (*is)(lua_state& state, int index);
25 const std::string& (*name)();
26 std::string (*print)(lua_state& state, int index);
29 std::list<luaclass_methods>& userdata_recogn_fns();
30 std::string try_recognize_userdata(lua_state& state, int index);
31 std::string try_print_userdata(lua_state& state, int index);
33 struct lua_function;
35 std::unordered_map<std::type_index, void*>& lua_class_types();
37 /**
38 * Group of functions.
40 class lua_function_group
42 public:
43 /**
44 * Create a group.
46 lua_function_group();
47 /**
48 * Destroy a group.
50 ~lua_function_group();
51 /**
52 * Add a function to group.
54 void do_register(const std::string& name, lua_function& fun);
55 /**
56 * Drop a function from group.
58 void do_unregister(const std::string& name);
59 /**
60 * Request callbacks on all currently registered functions.
62 void request_callback(std::function<void(std::string, lua_function*)> cb);
63 /**
64 * Bind a callback.
66 * Callbacks for all registered functions are immediately called.
68 int add_callback(std::function<void(std::string, lua_function*)> cb,
69 std::function<void(lua_function_group*)> dcb);
70 /**
71 * Unbind a calback.
73 void drop_callback(int handle);
74 private:
75 int next_handle;
76 std::map<std::string, lua_function*> functions;
77 std::map<int, std::function<void(std::string, lua_function*)>> callbacks;
78 std::map<int, std::function<void(lua_function_group*)>> dcallbacks;
81 /**
82 * Lua state object.
84 class lua_state
86 public:
87 //Auxillary type for store-tag.
88 template<typename T> struct _store_tag
90 T& addr;
91 T val;
92 _store_tag(T& a, T v) : addr(a), val(v) {}
94 //Auxillary type for vararg-tag.
95 struct vararg_tag
97 std::list<std::string> args;
98 vararg_tag(std::list<std::string>& _args) : args(_args) {}
99 int pushargs(lua_state& L);
102 //Auxillary type for numeric-tag.
103 template<typename T> struct _numeric_tag
105 T val;
106 _numeric_tag(T v) : val(v) {}
109 //Auxillary type for fnptr-tag.
110 template<typename T> struct _fnptr_tag
112 int(*fn)(lua_state& L, T v);
113 T val;
114 _fnptr_tag(int (*f)(lua_state& L, T v), T v) : fn(f), val(v) {}
117 //Auxillary type for fn-tag.
118 template<typename T> struct _fn_tag
120 T fn;
121 _fn_tag(T f) : fn(f) {}
125 * Callback parameter: Don't pass any real parameter, but instead store specified value in specified
126 * location.
128 * Parameter a: The location to store value to.
129 * Parameter v: The value to store.
130 * Returns: The parameter structure.
132 template<typename T> static struct _store_tag<T> store_tag(T& a, T v) { return _store_tag<T>(a, v); }
134 * Callback parameter: Pass numeric value.
136 * Parameter v: The value to pass.
137 * Returns: The parameter structure.
139 template<typename T> static struct _numeric_tag<T> numeric_tag(T v) { return _numeric_tag<T>(v); }
142 * Callback parameter: Execute function to push more parameters.
144 * Parameter f: The function to execute. The return value is number of additional parameters pushed.
145 * Parameter v: The value to pass to function.
146 * Returns: The parameter structure.
148 template<typename T> static struct _fnptr_tag<T> fnptr_tag(int (*f)(lua_state& L, T v), T v)
150 return _fnptr_tag<T>(f, v);
154 * Callback parameter: Execute function to push more parameters.
156 * Parameter v: The functor to execute. Passed reference to the Lua state. The return value is number of
157 * additional parameters pushed.
158 * Returns: The parameter structure.
160 template<typename T> static struct _fn_tag<T> fn_tag(T v) { return _fn_tag<T>(v); }
163 * Callback parameter: Pass boolean argument.
165 * Parameter v: The boolean value to pass.
167 struct boolean_tag { bool val; boolean_tag(bool v) : val(v) {}};
170 * Callback parameter: Pass string argument.
172 * Parameter v: The string value to pass.
174 struct string_tag { std::string val; string_tag(const std::string& v) : val(v) {}};
177 * Callback parameter: Pass nil argument.
179 struct nil_tag { nil_tag() {}};
180 private:
181 template<typename U, typename... T> void _callback(int argc, _store_tag<U> tag, T... args)
183 tag.addr = tag.val;
184 _callback(argc, args...);
185 tag.addr = NULL;
188 template<typename... T> void _callback(int argc, vararg_tag tag, T... args)
190 int e = tag.pushargs(*this);
191 _callback(argc + e, args...);
194 template<typename... T> void _callback(int argc, nil_tag tag, T... args)
196 pushnil();
197 _callback(argc + 1, args...);
200 template<typename... T> void _callback(int argc, boolean_tag tag, T... args)
202 pushboolean(tag.val);
203 _callback(argc + 1, args...);
206 template<typename... T> void _callback(int argc, string_tag tag, T... args)
208 pushlstring(tag.val.c_str(), tag.val.length());
209 _callback(argc + 1, args...);
212 template<typename U, typename... T> void _callback(int argc, _numeric_tag<U> tag, T... args)
214 pushnumber(tag.val);
215 _callback(argc + 1, args...);
218 template<typename U, typename... T> void _callback(int argc, _fnptr_tag<U> tag, T... args)
220 int extra = tag.fn(*this, tag.val);
221 _callback(argc + extra, args...);
224 template<typename U, typename... T> void _callback(int argc, _fn_tag<U> tag, T... args)
226 int extra = tag.fn(*this);
227 _callback(argc + extra, args...);
230 void _callback(int argc)
232 int r = pcall(argc, 0, 0);
233 if(r == LUA_ERRRUN) {
234 (stringfmt() << "Error running Lua callback: " << tostring(-1)).throwex();
235 pop(1);
237 if(r == LUA_ERRMEM) {
238 (stringfmt() << "Error running Lua callback: Out of memory").throwex();
239 pop(1);
241 if(r == LUA_ERRERR) {
242 (stringfmt() << "Error running Lua callback: Double Fault???").throwex();
243 pop(1);
246 public:
248 * Create a new state.
250 lua_state() throw(std::bad_alloc);
252 * Create a new state with specified master state.
254 lua_state(lua_state& _master, lua_State* L);
256 * Destroy a state.
258 ~lua_state() throw();
260 * Get the internal state object.
262 * Return value: Internal state.
264 lua_State* handle() { return lua_handle; }
266 * Get the master state.
268 lua_state& get_master() { return master ? master->get_master() : *this; }
270 * Set the internal state object.
272 void handle(lua_State* l) { lua_handle = l; }
274 * Set OOM handler.
276 void set_oom_handler(void (*oom)()) { oom_handler = oom ? oom : builtin_oom; }
278 * Reset the state.
280 void reset() throw(std::runtime_error, std::bad_alloc);
282 * Deinit the state.
284 void deinit() throw();
286 * Get a string argument.
288 * Parameter argindex: The stack index.
289 * Parameter fname: The name of function to use in error messages.
290 * Returns: The string.
291 * Throws std::runtime_error: The specified argument is not a string.
293 std::string get_string(int argindex, const std::string& fname) throw(std::runtime_error, std::bad_alloc)
295 if(lua_isnone(lua_handle, argindex))
296 (stringfmt() << "argument #" << argindex << " to " << fname << " must be string").throwex();
297 size_t len;
298 const char* f = lua_tolstring(lua_handle, argindex, &len);
299 if(!f)
300 (stringfmt() << "argument #" << argindex << " to " << fname << " must be string").throwex();
301 return std::string(f, f + len);
304 * Get a boolean argument.
306 * Parameter argindex: The stack index.
307 * Parameter fname: The name of function to use in error messages.
308 * Returns: The string.
309 * Throws std::runtime_error: The specified argument is not a boolean.
311 bool get_bool(int argindex, const std::string& fname) throw(std::runtime_error, std::bad_alloc)
313 if(lua_isnone(lua_handle, argindex) || !lua_isboolean(lua_handle, argindex))
314 (stringfmt() << "argument #" << argindex << " to " << fname << " must be boolean").throwex();
315 return (lua_toboolean(lua_handle, argindex) != 0);
318 * Get a mandatory numeric argument.
320 * Parameter argindex: The stack index.
321 * Parameter fname: The name of function to use in error messages.
322 * Returns: The parsed number.
323 * Throws std::runtime_error: Bad type.
325 template<typename T>
326 T get_numeric_argument(int argindex, const std::string& fname)
328 if(lua_isnone(lua_handle, argindex) || !lua_isnumber(lua_handle, argindex))
329 (stringfmt() << "Argument #" << argindex << " to " << fname << " must be numeric").throwex();
330 return static_cast<T>(lua_tonumber(lua_handle, argindex));
333 * Get a optional numeric argument.
335 * Parameter argindex: The stack index.
336 * Parameter value: The place to store the value.
337 * Parameter fname: The name of function to use in error messages.
338 * Throws std::runtime_error: Bad type.
340 template<typename T>
341 void get_numeric_argument(unsigned argindex, T& value, const std::string& fname)
343 if(lua_isnoneornil(lua_handle, argindex))
344 return;
345 if(lua_isnone(lua_handle, argindex) || !lua_isnumber(lua_handle, argindex))
346 (stringfmt() << "Argument #" << argindex << " to " << fname << " must be numeric if "
347 "present").throwex();
348 value = static_cast<T>(lua_tonumber(lua_handle, argindex));
351 * Do a callback.
353 * Parameter name: The name of the callback.
354 * Parameter args: Arguments to pass to the callback.
356 template<typename... T>
357 bool callback(const std::string& name, T... args)
359 getglobal(name.c_str());
360 int t = type(-1);
361 if(t != LUA_TFUNCTION) {
362 pop(1);
363 return false;
365 _callback(0, args...);
366 return true;
369 * Do a callback.
371 * Parameter cblist: List of environment keys to do callbacks.
372 * Parameter args: Arguments to pass to the callback.
374 template<typename... T>
375 bool callback(const std::list<char>& cblist, T... args)
377 bool any = false;
378 for(auto& i : cblist) {
379 pushlightuserdata(const_cast<char*>(&i));
380 rawget(LUA_REGISTRYINDEX);
381 int t = type(-1);
382 if(t != LUA_TFUNCTION) {
383 pop(1);
384 } else {
385 _callback(0, args...);
386 any = true;
389 return any;
392 * Add a group of functions.
394 void add_function_group(lua_function_group& group);
396 * Function callback.
398 void function_callback(const std::string& name, lua_function* func);
400 * Do something just once per VM.
402 * Parameter key: The do-once key value.
403 * Returns: True if called the first time for given key on given VM, false otherwise.
405 bool do_once(void* key);
407 * Callback list.
409 class lua_callback_list
411 public:
412 lua_callback_list(lua_state& L, const std::string& name, const std::string& fn_cbname = "");
413 ~lua_callback_list();
414 void _register(lua_state& L); //Reads callback from top of lua stack.
415 void _unregister(lua_state& L); //Reads callback from top of lua stack.
416 template<typename... T> bool callback(T... args) {
417 bool any = L.callback(callbacks, args...);
418 if(fn_cbname != "" && L.callback(fn_cbname, args...))
419 any = true;
420 return any;
422 const std::string& get_name() { return name; }
423 void clear() { callbacks.clear(); }
424 private:
425 lua_callback_list(const lua_callback_list&);
426 lua_callback_list& operator=(const lua_callback_list&);
427 std::list<char> callbacks;
428 lua_state& L;
429 std::string name;
430 std::string fn_cbname;
433 * Enumerate all callbacks.
435 std::list<lua_callback_list*> get_callbacks()
437 if(master)
438 return master->get_callbacks();
439 std::list<lua_callback_list*> r;
440 for(auto i : callbacks)
441 r.push_back(i.second);
442 return r;
445 * Register a callback.
447 class callback_proxy
449 public:
450 callback_proxy(lua_state& _L) : parent(_L) {}
451 void do_register(const std::string& name, lua_callback_list& callback)
453 parent.do_register_cb(name, callback);
456 * Unregister a callback.
458 void do_unregister(const std::string& name)
460 parent.do_unregister_cb(name);
462 private:
463 lua_state& parent;
466 void do_register_cb(const std::string& name, lua_callback_list& callback)
468 callbacks[name] = &callback;
471 void do_unregister_cb(const std::string& name)
473 callbacks.erase(name);
476 //All kinds of Lua API functions.
477 void pop(int n) { lua_pop(lua_handle, n); }
478 void* newuserdata(size_t size) { return lua_newuserdata(lua_handle, size); }
479 int setmetatable(int index) { return lua_setmetatable(lua_handle, index); }
480 int type(int index) { return lua_type(lua_handle, index); }
481 int getmetatable(int index) { return lua_getmetatable(lua_handle, index); }
482 int rawequal(int index1, int index2) { return lua_rawequal(lua_handle, index1, index2); }
483 void* touserdata(int index) { return lua_touserdata(lua_handle, index); }
484 const void* topointer(int index) { return lua_topointer(lua_handle, index); }
485 int gettop() { return lua_gettop(lua_handle); }
486 void pushvalue(int index) { lua_pushvalue(lua_handle, index); }
487 void pushlightuserdata(void* p) { lua_pushlightuserdata(lua_handle, p); }
488 void rawset(int index) { lua_rawset(lua_handle, index); }
489 void pushnil() { lua_pushnil(lua_handle); }
490 void pushstring(const char* s) { lua_pushstring(lua_handle, s); }
491 void rawget(int index) { lua_rawget(lua_handle, index); }
492 int isnil(int index) { return lua_isnil(lua_handle, index); }
493 void newtable() { lua_newtable(lua_handle); }
494 void pushcclosure(lua_CFunction fn, int n) { lua_pushcclosure(lua_handle, fn, n); }
495 void pushcfunction(lua_CFunction fn) { lua_pushcfunction(lua_handle, fn); }
496 void setfield(int index, const char* k) { lua_setfield(lua_handle, index, k); }
497 void getfield(int index, const char* k) { lua_getfield(lua_handle, index, k); }
498 void getglobal(const char* name) { lua_getglobal(lua_handle, name); }
499 void setglobal(const char* name) { lua_setglobal(lua_handle, name); }
500 void insert(int index) { lua_insert(lua_handle, index); }
501 void settable(int index) { lua_settable(lua_handle, index); }
502 int isnone(int index) { return lua_isnone(lua_handle, index); }
503 void pushnumber(lua_Number n) { return lua_pushnumber(lua_handle, n); }
504 int isnumber(int index) { return lua_isnumber(lua_handle, index); }
505 int isboolean(int index) { return lua_isboolean(lua_handle, index); }
506 int toboolean(int index) { return lua_toboolean(lua_handle, index); }
507 const char* tolstring(int index, size_t *len) { return lua_tolstring(lua_handle, index, len); }
508 void pushboolean(int b) { lua_pushboolean(lua_handle, b); }
509 lua_Number tonumber(int index) { return lua_tonumber(lua_handle, index); }
510 void gettable(int index) { lua_gettable(lua_handle, index); }
511 #if LUA_VERSION_NUM == 501
512 int load(lua_Reader reader, void* data, const char* chunkname) { return lua_load(lua_handle, reader, data,
513 chunkname); }
514 #endif
515 #if LUA_VERSION_NUM == 502
516 int load(lua_Reader reader, void* data, const char* chunkname, const char* mode) { return lua_load(lua_handle,
517 reader, data, chunkname, mode); }
518 #endif
519 const char* tostring(int index) { return lua_tostring(lua_handle, index); }
520 const char* tolstring(int index, size_t& len) { return lua_tolstring(lua_handle, index, &len); }
521 void pushlstring(const char* s, size_t len) { lua_pushlstring(lua_handle, s, len); }
522 void pushlstring(const std::string& s) { lua_pushlstring(lua_handle, s.c_str(), s.length()); }
523 void pushlstring(const char32_t* s, size_t len) { pushlstring(to_u8string(std::u32string(s, len))); }
524 int pcall(int nargs, int nresults, int errfunc) { return lua_pcall(lua_handle, nargs, nresults, errfunc); }
525 int next(int index) { return lua_next(lua_handle, index); }
526 int isnoneornil(int index) { return lua_isnoneornil(lua_handle, index); }
527 lua_Integer tointeger(int index) { return lua_tointeger(lua_handle, index); }
528 void rawgeti(int index, int n) { lua_rawgeti(lua_handle, index, n); }
529 callback_proxy cbproxy;
530 private:
531 static void builtin_oom();
532 static void* builtin_alloc(void* user, void* old, size_t olds, size_t news);
533 void (*oom_handler)();
534 lua_state* master;
535 lua_State* lua_handle;
536 std::set<std::pair<lua_function_group*, int>> function_groups;
537 std::map<std::string, lua_callback_list*> callbacks;
538 lua_state(lua_state&);
539 lua_state& operator=(lua_state&);
543 * Pin of an object against Lua GC.
545 template<typename T> struct lua_obj_pin
548 * Create a null pin.
550 lua_obj_pin()
552 state = NULL;
553 obj = NULL;
556 * Create a new pin.
558 * Parameter _state: The state to pin the object in.
559 * Parameter _object: The object to pin.
561 lua_obj_pin(lua_state& _state, T* _object)
562 : state(&_state.get_master())
564 _state.pushlightuserdata(this);
565 _state.pushvalue(-2);
566 _state.rawset(LUA_REGISTRYINDEX);
567 obj = _object;
570 * Delete a pin.
572 ~lua_obj_pin() throw()
574 if(obj) {
575 state->pushlightuserdata(this);
576 state->pushnil();
577 state->rawset(LUA_REGISTRYINDEX);
581 * Copy ctor.
583 lua_obj_pin(const lua_obj_pin& p)
585 state = p.state;
586 obj = p.obj;
587 if(obj) {
588 state->pushlightuserdata(this);
589 state->pushlightuserdata(const_cast<lua_obj_pin*>(&p));
590 state->rawget(LUA_REGISTRYINDEX);
591 state->rawset(LUA_REGISTRYINDEX);
595 * Assignment operator.
597 lua_obj_pin& operator=(const lua_obj_pin& p)
599 if(state == p.state && obj == p.obj)
600 return *this;
601 if(obj == p.obj)
602 throw std::logic_error("A Lua object can't be in two lua states at once");
603 if(obj) {
604 state->pushlightuserdata(this);
605 state->pushnil();
606 state->rawset(LUA_REGISTRYINDEX);
608 state = p.state;
609 if(p.obj) {
610 state->pushlightuserdata(this);
611 state->pushlightuserdata(const_cast<lua_obj_pin*>(&p));
612 state->rawget(LUA_REGISTRYINDEX);
613 state->rawset(LUA_REGISTRYINDEX);
615 obj = p.obj;
616 return *this;
619 * Clear a pinned object.
621 void clear()
623 if(obj) {
624 state->pushlightuserdata(this);
625 state->pushnil();
626 state->rawset(LUA_REGISTRYINDEX);
628 state = NULL;
629 obj = NULL;
632 * Get pointer to pinned object.
634 * Returns: The pinned object.
636 T* object() { return obj; }
638 * Is non-null?
640 operator bool() { return obj != NULL; }
642 * Smart pointer.
644 T& operator*() { if(obj) return *obj; throw std::runtime_error("Attempted to reference NULL Lua pin"); }
645 T* operator->() { if(obj) return obj; throw std::runtime_error("Attempted to reference NULL Lua pin"); }
647 * Push Lua value.
649 void luapush(lua_state& state)
651 state.pushlightuserdata(this);
652 state.rawget(LUA_REGISTRYINDEX);
654 private:
655 T* obj;
656 lua_state* state;
659 template<typename T> void* unbox_any_pin(struct lua_obj_pin<T>* pin)
661 return pin ? pin->object() : NULL;
665 * Helper class containing binding data for Lua class call.
667 template<class T> struct lua_class_bind_data
670 * The pointer to call.
672 int (T::*fn)(lua_state& state, const std::string& _fname);
674 * The state to call it in.
676 lua_state* state;
678 * The name of the method to pass.
680 char fname[];
683 template<class T> class lua_class;
686 * Function to obtain class object for given Lua class.
688 template<class T> lua_class<T>& objclass()
690 return *reinterpret_cast<lua_class<T>*>(lua_class_types()[typeid(T)]);
693 template<class T> struct lua_class_binding
696 * Name.
698 const char* name;
700 * Function.
702 int (T::*fn)(lua_state& LS, const std::string& fname);
706 * The type of Lua classes.
708 template<class T> class lua_class
710 template<typename... U> T* _create(lua_state& state, U... args)
712 void* obj = state.newuserdata(sizeof(T));
713 load_metatable(state);
714 state.setmetatable(-2);
715 T* _obj = reinterpret_cast<T*>(obj);
716 new(_obj) T(state, args...);
717 return _obj;
720 static int class_bind_trampoline(lua_State* LS)
722 try {
723 lua_class_bind_data<T>* b = (lua_class_bind_data<T>*)lua_touserdata(LS, lua_upvalueindex(1));
724 lua_state L(*b->state, LS);
725 T* p = lua_class<T>::get(L, 1, b->fname);
726 return (p->*(b->fn))(L, b->fname);
727 } catch(std::exception& e) {
728 std::string err = e.what();
729 lua_pushlstring(LS, err.c_str(), err.length());
730 lua_error(LS);
734 T* _get(lua_state& state, int arg, const std::string& fname, bool optional = false)
736 if(state.type(arg) == LUA_TNONE || state.type(arg) == LUA_TNIL) {
737 if(optional)
738 return NULL;
739 else
740 goto badtype;
742 load_metatable(state);
743 if(!state.getmetatable(arg))
744 goto badtype;
745 if(!state.rawequal(-1, -2))
746 goto badtype;
747 state.pop(2);
748 return reinterpret_cast<T*>(state.touserdata(arg));
749 badtype:
750 (stringfmt() << "argument #" << arg << " to " << fname << " must be " << name).throwex();
751 return NULL; //Never reached.
754 bool _is(lua_state& state, int arg)
756 if(state.type(arg) != LUA_TUSERDATA)
757 return false;
758 load_metatable(state);
759 if(!state.getmetatable(arg)) {
760 state.pop(1);
761 return false;
763 bool ret = state.rawequal(-1, -2);
764 state.pop(2);
765 return ret;
768 lua_obj_pin<T> _pin(lua_state& state, int arg, const std::string& fname)
770 T* obj = get(state, arg, fname);
771 state.pushvalue(arg);
772 return lua_obj_pin<T>(state, obj);
774 public:
776 * Create a new Lua class.
778 * Parameter _name: The name of the class.
780 lua_class(const std::string& _name)
782 name = _name;
783 luaclass_methods m;
784 m.is = lua_class<T>::is;
785 m.name = lua_class<T>::get_name;
786 m.print = lua_class<T>::print;
787 userdata_recogn_fns().push_back(m);
788 lua_class_types()[typeid(T)] = this;
792 * Create a new instance of object.
794 * Parameter state: The Lua state to create the object in.
795 * Parameter args: The arguments to pass to class constructor.
797 template<typename... U> static T* create(lua_state& state, U... args)
799 return objclass<T>()._create(state, args...);
803 * Bind a method to class.
805 * Parameter state: The state to do the binding in.
806 * Parameter keyname: The name of the method.
807 * Parameter fn: The method to call.
808 * Parameter force: If true, overwrite existing method.
810 void bind(lua_state& state, const char* keyname, int (T::*fn)(lua_state& LS, const std::string& fname))
812 load_metatable(state);
813 state.pushstring(keyname);
814 std::string fname = name + std::string("::") + keyname;
815 void* ptr = state.newuserdata(sizeof(lua_class_bind_data<T>) + fname.length() + 1);
816 lua_class_bind_data<T>* bdata = reinterpret_cast<lua_class_bind_data<T>*>(ptr);
817 bdata->fn = fn;
818 bdata->state = &state.get_master();
819 std::copy(fname.begin(), fname.end(), bdata->fname);
820 bdata->fname[fname.length()] = 0;
821 state.pushcclosure(class_bind_trampoline, 1);
822 state.rawset(-3);
823 state.pop(1);
826 * Bind multiple at once.
828 void bind_multi(lua_state& state, std::initializer_list<lua_class_binding<T>> list, void* doonce_key = NULL)
830 static char once_key;
831 if(state.do_once(doonce_key ? doonce_key : &once_key))
832 for(auto i : list)
833 bind(state, i.name, i.fn);
836 * Get a pointer to the object.
838 * Parameter state: The Lua state.
839 * Parameter arg: Argument index.
840 * Parameter fname: The name of function for error messages.
841 * Parameter optional: If true and argument is NIL or none, return NULL.
842 * Throws std::runtime_error: Wrong type.
844 static T* get(lua_state& state, int arg, const std::string& fname, bool optional = false)
845 throw(std::bad_alloc, std::runtime_error)
847 return objclass<T>()._get(state, arg, fname, optional);
851 * Identify if object is of this type.
853 * Parameter state: The Lua state.
854 * Parameter arg: Argument index.
855 * Returns: True if object is of specified type, false if not.
857 static bool is(lua_state& state, int arg) throw()
859 return objclass<T>()._is(state, arg);
862 * Get name of class.
864 static const std::string& get_name()
866 return objclass<T>().name;
869 * Format instance of this class as string.
871 static std::string print(lua_state& state, int index)
873 T* obj = get(state, index, "__internal_print");
874 return obj->print();
877 * Get a pin of object against Lua GC.
879 * Parameter state: The Lua state.
880 * Parameter arg: Argument index.
881 * Parameter fname: Name of function for error message purposes.
882 * Throws std::runtime_error: Wrong type.
884 static lua_obj_pin<T> pin(lua_state& state, int arg, const std::string& fname) throw(std::bad_alloc,
885 std::runtime_error)
887 return objclass<T>()._pin(state, arg, fname);
889 private:
890 static int dogc(lua_State* LS)
892 T* obj = reinterpret_cast<T*>(lua_touserdata(LS, 1));
893 obj->~T();
894 return 0;
897 static int newindex(lua_State* LS)
899 lua_pushstring(LS, "Writing metatables of classes is not allowed");
900 lua_error(LS);
901 return 0;
904 static int index(lua_State* LS)
906 lua_getmetatable(LS, 1);
907 lua_pushvalue(LS, 2);
908 lua_rawget(LS, -2);
909 return 1;
912 void load_metatable(lua_state& state)
914 again:
915 state.pushlightuserdata(this);
916 state.rawget(LUA_REGISTRYINDEX);
917 if(state.type(-1) == LUA_TNIL) {
918 state.pop(1);
919 state.pushlightuserdata(this);
920 state.newtable();
921 state.pushvalue(-1);
922 state.setmetatable(-2);
923 state.pushstring("__gc");
924 state.pushcfunction(&lua_class<T>::dogc);
925 state.rawset(-3);
926 state.pushstring("__newindex");
927 state.pushcfunction(&lua_class<T>::newindex);
928 state.rawset(-3);
929 state.pushstring("__index");
930 state.pushcfunction(&lua_class<T>::index);
931 state.rawset(-3);
932 state.rawset(LUA_REGISTRYINDEX);
933 goto again;
936 std::string name;
937 lua_class(const lua_class<T>&);
938 lua_class& operator=(const lua_class<T>&);
942 * Function implemented in C++ exported to Lua.
944 class lua_function
946 public:
948 * Register function.
950 lua_function(lua_function_group& group, const std::string& name) throw(std::bad_alloc);
952 * Unregister function.
954 virtual ~lua_function() throw();
957 * Invoke function.
959 virtual int invoke(lua_state& L) = 0;
960 protected:
961 std::string fname;
962 lua_function_group& group;
966 * Register function pointer as lua function.
968 class function_ptr_luafun : public lua_function
970 public:
972 * Register.
974 function_ptr_luafun(lua_function_group& group, const std::string& name,
975 int (*_fn)(lua_state& L, const std::string& fname))
976 : lua_function(group, name)
978 fn = _fn;
981 * Invoke function.
983 int invoke(lua_state& L)
985 return fn(L, fname);
987 private:
988 int (*fn)(lua_state& L, const std::string& fname);
992 #endif