Save bitmaps as PNG
[lsnes.git] / include / library / luabase.hpp
blob9977358dd564b18675019739f0c1d5801907f7da
1 #ifndef _library__luabase__hpp__included__
2 #define _library__luabase__hpp__included__
4 #include <string>
5 #include <stdexcept>
6 #include <map>
7 #include <set>
8 #include <list>
9 #include <cassert>
10 #include "string.hpp"
11 #include "utf8.hpp"
12 extern "C"
14 #include <lua.h>
17 class lua_state;
19 struct luaclass_methods
21 bool (*is)(lua_state& state, int index);
22 const std::string& (*name)();
23 std::string (*print)(lua_state& state, int index);
26 std::list<luaclass_methods>& userdata_recogn_fns();
27 std::string try_recognize_userdata(lua_state& state, int index);
28 std::string try_print_userdata(lua_state& state, int index);
30 struct lua_function;
32 /**
33 * Group of functions.
35 class lua_function_group
37 public:
38 /**
39 * Create a group.
41 lua_function_group();
42 /**
43 * Destroy a group.
45 ~lua_function_group();
46 /**
47 * Add a function to group.
49 void do_register(const std::string& name, lua_function& fun);
50 /**
51 * Drop a function from group.
53 void do_unregister(const std::string& name);
54 /**
55 * Request callbacks on all currently registered functions.
57 void request_callback(std::function<void(std::string, lua_function*)> cb);
58 /**
59 * Bind a callback.
61 * Callbacks for all registered functions are immediately called.
63 int add_callback(std::function<void(std::string, lua_function*)> cb,
64 std::function<void(lua_function_group*)> dcb);
65 /**
66 * Unbind a calback.
68 void drop_callback(int handle);
69 private:
70 int next_handle;
71 std::map<std::string, lua_function*> functions;
72 std::map<int, std::function<void(std::string, lua_function*)>> callbacks;
73 std::map<int, std::function<void(lua_function_group*)>> dcallbacks;
76 /**
77 * Lua state object.
79 class lua_state
81 public:
82 //Auxillary type for store-tag.
83 template<typename T> struct _store_tag
85 T& addr;
86 T val;
87 _store_tag(T& a, T v) : addr(a), val(v) {}
89 //Auxillary type for vararg-tag.
90 struct vararg_tag
92 std::list<std::string> args;
93 vararg_tag(std::list<std::string>& _args) : args(_args) {}
94 int pushargs(lua_state& L);
97 //Auxillary type for numeric-tag.
98 template<typename T> struct _numeric_tag
100 T val;
101 _numeric_tag(T v) : val(v) {}
104 //Auxillary type for fnptr-tag.
105 template<typename T> struct _fnptr_tag
107 int(*fn)(lua_state& L, T v);
108 T val;
109 _fnptr_tag(int (*f)(lua_state& L, T v), T v) : fn(f), val(v) {}
112 //Auxillary type for fn-tag.
113 template<typename T> struct _fn_tag
115 T fn;
116 _fn_tag(T f) : fn(f) {}
120 * Callback parameter: Don't pass any real parameter, but instead store specified value in specified
121 * location.
123 * Parameter a: The location to store value to.
124 * Parameter v: The value to store.
125 * Returns: The parameter structure.
127 template<typename T> static struct _store_tag<T> store_tag(T& a, T v) { return _store_tag<T>(a, v); }
129 * Callback parameter: Pass numeric value.
131 * Parameter v: The value to pass.
132 * Returns: The parameter structure.
134 template<typename T> static struct _numeric_tag<T> numeric_tag(T v) { return _numeric_tag<T>(v); }
137 * Callback parameter: Execute function to push more parameters.
139 * Parameter f: The function to execute. The return value is number of additional parameters pushed.
140 * Parameter v: The value to pass to function.
141 * Returns: The parameter structure.
143 template<typename T> static struct _fnptr_tag<T> fnptr_tag(int (*f)(lua_state& L, T v), T v)
145 return _fnptr_tag<T>(f, v);
149 * Callback parameter: Execute function to push more parameters.
151 * Parameter v: The functor to execute. Passed reference to the Lua state. The return value is number of
152 * additional parameters pushed.
153 * Returns: The parameter structure.
155 template<typename T> static struct _fn_tag<T> fn_tag(T v) { return _fn_tag<T>(v); }
158 * Callback parameter: Pass boolean argument.
160 * Parameter v: The boolean value to pass.
162 struct boolean_tag { bool val; boolean_tag(bool v) : val(v) {}};
165 * Callback parameter: Pass string argument.
167 * Parameter v: The string value to pass.
169 struct string_tag { std::string val; string_tag(const std::string& v) : val(v) {}};
172 * Callback parameter: Pass nil argument.
174 struct nil_tag { nil_tag() {}};
175 private:
176 template<typename U, typename... T> void _callback(int argc, _store_tag<U> tag, T... args)
178 tag.addr = tag.val;
179 _callback(argc, args...);
180 tag.addr = NULL;
183 template<typename... T> void _callback(int argc, vararg_tag tag, T... args)
185 int e = tag.pushargs(*this);
186 _callback(argc + e, args...);
189 template<typename... T> void _callback(int argc, nil_tag tag, T... args)
191 pushnil();
192 _callback(argc + 1, args...);
195 template<typename... T> void _callback(int argc, boolean_tag tag, T... args)
197 pushboolean(tag.val);
198 _callback(argc + 1, args...);
201 template<typename... T> void _callback(int argc, string_tag tag, T... args)
203 pushlstring(tag.val.c_str(), tag.val.length());
204 _callback(argc + 1, args...);
207 template<typename U, typename... T> void _callback(int argc, _numeric_tag<U> tag, T... args)
209 pushnumber(tag.val);
210 _callback(argc + 1, args...);
213 template<typename U, typename... T> void _callback(int argc, _fnptr_tag<U> tag, T... args)
215 int extra = tag.fn(*this, tag.val);
216 _callback(argc + extra, args...);
219 template<typename U, typename... T> void _callback(int argc, _fn_tag<U> tag, T... args)
221 int extra = tag.fn(*this);
222 _callback(argc + extra, args...);
225 void _callback(int argc)
227 int r = pcall(argc, 0, 0);
228 if(r == LUA_ERRRUN) {
229 (stringfmt() << "Error running Lua callback: " << tostring(-1)).throwex();
230 pop(1);
232 if(r == LUA_ERRMEM) {
233 (stringfmt() << "Error running Lua callback: Out of memory").throwex();
234 pop(1);
236 if(r == LUA_ERRERR) {
237 (stringfmt() << "Error running Lua callback: Double Fault???").throwex();
238 pop(1);
241 public:
243 * Create a new state.
245 lua_state() throw(std::bad_alloc);
247 * Create a new state with specified master state.
249 lua_state(lua_state& _master, lua_State* L);
251 * Destroy a state.
253 ~lua_state() throw();
255 * Get the internal state object.
257 * Return value: Internal state.
259 lua_State* handle() { return lua_handle; }
261 * Get the master state.
263 lua_state& get_master() { return master ? master->get_master() : *this; }
265 * Set the internal state object.
267 void handle(lua_State* l) { lua_handle = l; }
269 * Set OOM handler.
271 void set_oom_handler(void (*oom)()) { oom_handler = oom ? oom : builtin_oom; }
273 * Reset the state.
275 void reset() throw(std::runtime_error, std::bad_alloc);
277 * Deinit the state.
279 void deinit() throw();
281 * Get a string argument.
283 * Parameter argindex: The stack index.
284 * Parameter fname: The name of function to use in error messages.
285 * Returns: The string.
286 * Throws std::runtime_error: The specified argument is not a string.
288 std::string get_string(int argindex, const std::string& fname) throw(std::runtime_error, std::bad_alloc)
290 if(lua_isnone(lua_handle, argindex))
291 (stringfmt() << "argument #" << argindex << " to " << fname << " must be string").throwex();
292 size_t len;
293 const char* f = lua_tolstring(lua_handle, argindex, &len);
294 if(!f)
295 (stringfmt() << "argument #" << argindex << " to " << fname << " must be string").throwex();
296 return std::string(f, f + len);
299 * Get a boolean argument.
301 * Parameter argindex: The stack index.
302 * Parameter fname: The name of function to use in error messages.
303 * Returns: The string.
304 * Throws std::runtime_error: The specified argument is not a boolean.
306 bool get_bool(int argindex, const std::string& fname) throw(std::runtime_error, std::bad_alloc)
308 if(lua_isnone(lua_handle, argindex) || !lua_isboolean(lua_handle, argindex))
309 (stringfmt() << "argument #" << argindex << " to " << fname << " must be boolean").throwex();
310 return (lua_toboolean(lua_handle, argindex) != 0);
313 * Get a mandatory numeric argument.
315 * Parameter argindex: The stack index.
316 * Parameter fname: The name of function to use in error messages.
317 * Returns: The parsed number.
318 * Throws std::runtime_error: Bad type.
320 template<typename T>
321 T get_numeric_argument(int argindex, const std::string& fname)
323 if(lua_isnone(lua_handle, argindex) || !lua_isnumber(lua_handle, argindex))
324 (stringfmt() << "Argunment #" << argindex << " to " << fname << " must be numeric").throwex();
325 return static_cast<T>(lua_tonumber(lua_handle, argindex));
328 * Get a optional numeric argument.
330 * Parameter argindex: The stack index.
331 * Parameter value: The place to store the value.
332 * Parameter fname: The name of function to use in error messages.
333 * Throws std::runtime_error: Bad type.
335 template<typename T>
336 void get_numeric_argument(unsigned argindex, T& value, const std::string& fname)
338 if(lua_isnoneornil(lua_handle, argindex))
339 return;
340 if(lua_isnone(lua_handle, argindex) || !lua_isnumber(lua_handle, argindex))
341 (stringfmt() << "Argunment #" << argindex << " to " << fname << " must be numeric if "
342 "present").throwex();
343 value = static_cast<T>(lua_tonumber(lua_handle, argindex));
346 * Do a callback.
348 * Parameter name: The name of the callback.
349 * Parameter args: Arguments to pass to the callback.
351 template<typename... T>
352 bool callback(const std::string& name, T... args)
354 getglobal(name.c_str());
355 int t = type(-1);
356 if(t != LUA_TFUNCTION) {
357 pop(1);
358 return false;
360 _callback(0, args...);
361 return true;
364 * Do a callback.
366 * Parameter cblist: List of environment keys to do callbacks.
367 * Parameter args: Arguments to pass to the callback.
369 template<typename... T>
370 bool callback(const std::list<char>& cblist, T... args)
372 bool any = false;
373 for(auto& i : cblist) {
374 pushlightuserdata(const_cast<char*>(&i));
375 rawget(LUA_REGISTRYINDEX);
376 int t = type(-1);
377 if(t != LUA_TFUNCTION) {
378 pop(1);
379 } else {
380 _callback(0, args...);
381 any = true;
384 return any;
387 * Add a group of functions.
389 void add_function_group(lua_function_group& group);
391 * Function callback.
393 void function_callback(const std::string& name, lua_function* func);
395 * Do something just once per VM.
397 * Parameter key: The do-once key value.
398 * Returns: True if called the first time for given key on given VM, false otherwise.
400 bool do_once(void* key);
402 * Callback list.
404 class lua_callback_list
406 public:
407 lua_callback_list(lua_state& L, const std::string& name, const std::string& fn_cbname = "");
408 ~lua_callback_list();
409 void _register(lua_state& L); //Reads callback from top of lua stack.
410 void _unregister(lua_state& L); //Reads callback from top of lua stack.
411 template<typename... T> bool callback(T... args) {
412 bool any = L.callback(callbacks, args...);
413 if(fn_cbname != "" && L.callback(fn_cbname, args...))
414 any = true;
415 return any;
417 const std::string& get_name() { return name; }
418 void clear() { callbacks.clear(); }
419 private:
420 lua_callback_list(const lua_callback_list&);
421 lua_callback_list& operator=(const lua_callback_list&);
422 std::list<char> callbacks;
423 lua_state& L;
424 std::string name;
425 std::string fn_cbname;
428 * Enumerate all callbacks.
430 std::list<lua_callback_list*> get_callbacks()
432 if(master)
433 return master->get_callbacks();
434 std::list<lua_callback_list*> r;
435 for(auto i : callbacks)
436 r.push_back(i.second);
437 return r;
440 * Register a callback.
442 class callback_proxy
444 public:
445 callback_proxy(lua_state& _L) : parent(_L) {}
446 void do_register(const std::string& name, lua_callback_list& callback)
448 parent.do_register_cb(name, callback);
451 * Unregister a callback.
453 void do_unregister(const std::string& name)
455 parent.do_unregister_cb(name);
457 private:
458 lua_state& parent;
461 void do_register_cb(const std::string& name, lua_callback_list& callback)
463 callbacks[name] = &callback;
466 void do_unregister_cb(const std::string& name)
468 callbacks.erase(name);
471 //All kinds of Lua API functions.
472 void pop(int n) { lua_pop(lua_handle, n); }
473 void* newuserdata(size_t size) { return lua_newuserdata(lua_handle, size); }
474 int setmetatable(int index) { return lua_setmetatable(lua_handle, index); }
475 int type(int index) { return lua_type(lua_handle, index); }
476 int getmetatable(int index) { return lua_getmetatable(lua_handle, index); }
477 int rawequal(int index1, int index2) { return lua_rawequal(lua_handle, index1, index2); }
478 void* touserdata(int index) { return lua_touserdata(lua_handle, index); }
479 const void* topointer(int index) { return lua_topointer(lua_handle, index); }
480 int gettop() { return lua_gettop(lua_handle); }
481 void pushvalue(int index) { lua_pushvalue(lua_handle, index); }
482 void pushlightuserdata(void* p) { lua_pushlightuserdata(lua_handle, p); }
483 void rawset(int index) { lua_rawset(lua_handle, index); }
484 void pushnil() { lua_pushnil(lua_handle); }
485 void pushstring(const char* s) { lua_pushstring(lua_handle, s); }
486 void rawget(int index) { lua_rawget(lua_handle, index); }
487 int isnil(int index) { return lua_isnil(lua_handle, index); }
488 void newtable() { lua_newtable(lua_handle); }
489 void pushcclosure(lua_CFunction fn, int n) { lua_pushcclosure(lua_handle, fn, n); }
490 void pushcfunction(lua_CFunction fn) { lua_pushcfunction(lua_handle, fn); }
491 void setfield(int index, const char* k) { lua_setfield(lua_handle, index, k); }
492 void getfield(int index, const char* k) { lua_getfield(lua_handle, index, k); }
493 void getglobal(const char* name) { lua_getglobal(lua_handle, name); }
494 void setglobal(const char* name) { lua_setglobal(lua_handle, name); }
495 void insert(int index) { lua_insert(lua_handle, index); }
496 void settable(int index) { lua_settable(lua_handle, index); }
497 int isnone(int index) { return lua_isnone(lua_handle, index); }
498 void pushnumber(lua_Number n) { return lua_pushnumber(lua_handle, n); }
499 int isnumber(int index) { return lua_isnumber(lua_handle, index); }
500 int isboolean(int index) { return lua_isboolean(lua_handle, index); }
501 int toboolean(int index) { return lua_toboolean(lua_handle, index); }
502 const char* tolstring(int index, size_t *len) { return lua_tolstring(lua_handle, index, len); }
503 void pushboolean(int b) { lua_pushboolean(lua_handle, b); }
504 lua_Number tonumber(int index) { return lua_tonumber(lua_handle, index); }
505 void gettable(int index) { lua_gettable(lua_handle, index); }
506 #if LUA_VERSION_NUM == 501
507 int load(lua_Reader reader, void* data, const char* chunkname) { return lua_load(lua_handle, reader, data,
508 chunkname); }
509 #endif
510 #if LUA_VERSION_NUM == 502
511 int load(lua_Reader reader, void* data, const char* chunkname, const char* mode) { return lua_load(lua_handle,
512 reader, data, chunkname, mode); }
513 #endif
514 const char* tostring(int index) { return lua_tostring(lua_handle, index); }
515 const char* tolstring(int index, size_t& len) { return lua_tolstring(lua_handle, index, &len); }
516 void pushlstring(const char* s, size_t len) { lua_pushlstring(lua_handle, s, len); }
517 void pushlstring(const std::string& s) { lua_pushlstring(lua_handle, s.c_str(), s.length()); }
518 void pushlstring(const char32_t* s, size_t len) { pushlstring(to_u8string(std::u32string(s, len))); }
519 int pcall(int nargs, int nresults, int errfunc) { return lua_pcall(lua_handle, nargs, nresults, errfunc); }
520 int next(int index) { return lua_next(lua_handle, index); }
521 int isnoneornil(int index) { return lua_isnoneornil(lua_handle, index); }
522 lua_Integer tointeger(int index) { return lua_tointeger(lua_handle, index); }
523 void rawgeti(int index, int n) { lua_rawgeti(lua_handle, index, n); }
524 callback_proxy cbproxy;
525 private:
526 static void builtin_oom();
527 static void* builtin_alloc(void* user, void* old, size_t olds, size_t news);
528 void (*oom_handler)();
529 lua_state* master;
530 lua_State* lua_handle;
531 std::set<std::pair<lua_function_group*, int>> function_groups;
532 std::map<std::string, lua_callback_list*> callbacks;
533 lua_state(lua_state&);
534 lua_state& operator=(lua_state&);
538 * Pin of an object against Lua GC.
540 template<typename T> struct lua_obj_pin
543 * Create a null pin.
545 lua_obj_pin()
547 state = NULL;
548 obj = NULL;
551 * Create a new pin.
553 * Parameter _state: The state to pin the object in.
554 * Parameter _object: The object to pin.
556 lua_obj_pin(lua_state& _state, T* _object)
557 : state(&_state.get_master())
559 _state.pushlightuserdata(this);
560 _state.pushvalue(-2);
561 _state.rawset(LUA_REGISTRYINDEX);
562 obj = _object;
565 * Delete a pin.
567 ~lua_obj_pin() throw()
569 if(obj) {
570 state->pushlightuserdata(this);
571 state->pushnil();
572 state->rawset(LUA_REGISTRYINDEX);
576 * Copy ctor.
578 lua_obj_pin(const lua_obj_pin& p)
580 state = p.state;
581 obj = p.obj;
582 if(obj) {
583 state->pushlightuserdata(this);
584 state->pushlightuserdata(const_cast<lua_obj_pin*>(&p));
585 state->rawget(LUA_REGISTRYINDEX);
586 state->rawset(LUA_REGISTRYINDEX);
590 * Assignment operator.
592 lua_obj_pin& operator=(const lua_obj_pin& p)
594 if(state == p.state && obj == p.obj)
595 return *this;
596 if(obj == p.obj)
597 throw std::logic_error("A Lua object can't be in two lua states at once");
598 if(obj) {
599 state->pushlightuserdata(this);
600 state->pushnil();
601 state->rawset(LUA_REGISTRYINDEX);
603 state = p.state;
604 if(p.obj) {
605 state->pushlightuserdata(this);
606 state->pushlightuserdata(const_cast<lua_obj_pin*>(&p));
607 state->rawget(LUA_REGISTRYINDEX);
608 state->rawset(LUA_REGISTRYINDEX);
610 obj = p.obj;
611 return *this;
614 * Clear a pinned object.
616 void clear()
618 if(obj) {
619 state->pushlightuserdata(this);
620 state->pushnil();
621 state->rawset(LUA_REGISTRYINDEX);
623 state = NULL;
624 obj = NULL;
627 * Get pointer to pinned object.
629 * Returns: The pinned object.
631 T* object() { return obj; }
633 * Is non-null?
635 operator bool() { return obj != NULL; }
637 * Smart pointer.
639 T& operator*() { if(obj) return *obj; throw std::runtime_error("Attempted to reference NULL Lua pin"); }
640 T* operator->() { if(obj) return obj; throw std::runtime_error("Attempted to reference NULL Lua pin"); }
642 * Push Lua value.
644 void luapush(lua_state& state)
646 state.pushlightuserdata(this);
647 state.rawget(LUA_REGISTRYINDEX);
649 private:
650 T* obj;
651 lua_state* state;
654 template<typename T> void* unbox_any_pin(struct lua_obj_pin<T>* pin)
656 return pin ? pin->object() : NULL;
660 * Helper class containing binding data for Lua class call.
662 template<class T> struct lua_class_bind_data
665 * The pointer to call.
667 int (T::*fn)(lua_state& state, const std::string& _fname);
669 * The state to call it in.
671 lua_state* state;
673 * The name of the method to pass.
675 char fname[];
678 template<class T> class lua_class;
681 * Function to obtain class object for given Lua class.
683 template<class T> lua_class<T>& objclass();
685 template<class T> struct lua_class_binding
688 * Name.
690 const char* name;
692 * Function.
694 int (T::*fn)(lua_state& LS, const std::string& fname);
698 * The type of Lua classes.
700 template<class T> class lua_class
702 template<typename... U> T* _create(lua_state& state, U... args)
704 void* obj = state.newuserdata(sizeof(T));
705 load_metatable(state);
706 state.setmetatable(-2);
707 T* _obj = reinterpret_cast<T*>(obj);
708 new(_obj) T(state, args...);
709 return _obj;
712 static int class_bind_trampoline(lua_State* LS)
714 try {
715 lua_class_bind_data<T>* b = (lua_class_bind_data<T>*)lua_touserdata(LS, lua_upvalueindex(1));
716 lua_state L(*b->state, LS);
717 T* p = lua_class<T>::get(L, 1, b->fname);
718 return (p->*(b->fn))(L, b->fname);
719 } catch(std::exception& e) {
720 std::string err = e.what();
721 lua_pushlstring(LS, err.c_str(), err.length());
722 lua_error(LS);
726 T* _get(lua_state& state, int arg, const std::string& fname, bool optional = false)
728 if(state.type(arg) == LUA_TNONE || state.type(arg) == LUA_TNIL) {
729 if(optional)
730 return NULL;
731 else
732 goto badtype;
734 load_metatable(state);
735 if(!state.getmetatable(arg))
736 goto badtype;
737 if(!state.rawequal(-1, -2))
738 goto badtype;
739 state.pop(2);
740 return reinterpret_cast<T*>(state.touserdata(arg));
741 badtype:
742 (stringfmt() << "argument #" << arg << " to " << fname << " must be " << name).throwex();
743 return NULL; //Never reached.
746 bool _is(lua_state& state, int arg)
748 if(state.type(arg) != LUA_TUSERDATA)
749 return false;
750 load_metatable(state);
751 if(!state.getmetatable(arg)) {
752 state.pop(1);
753 return false;
755 bool ret = state.rawequal(-1, -2);
756 state.pop(2);
757 return ret;
760 lua_obj_pin<T> _pin(lua_state& state, int arg, const std::string& fname)
762 T* obj = get(state, arg, fname);
763 state.pushvalue(arg);
764 return lua_obj_pin<T>(state, obj);
766 public:
768 * Create a new Lua class.
770 * Parameter _name: The name of the class.
772 lua_class(const std::string& _name)
774 name = _name;
775 luaclass_methods m;
776 m.is = lua_class<T>::is;
777 m.name = lua_class<T>::get_name;
778 m.print = lua_class<T>::print;
779 userdata_recogn_fns().push_back(m);
783 * Create a new instance of object.
785 * Parameter state: The Lua state to create the object in.
786 * Parameter args: The arguments to pass to class constructor.
788 template<typename... U> static T* create(lua_state& state, U... args)
790 return objclass<T>()._create(state, args...);
794 * Bind a method to class.
796 * Parameter state: The state to do the binding in.
797 * Parameter keyname: The name of the method.
798 * Parameter fn: The method to call.
799 * Parameter force: If true, overwrite existing method.
801 void bind(lua_state& state, const char* keyname, int (T::*fn)(lua_state& LS, const std::string& fname))
803 load_metatable(state);
804 state.pushstring(keyname);
805 std::string fname = name + std::string("::") + keyname;
806 void* ptr = state.newuserdata(sizeof(lua_class_bind_data<T>) + fname.length() + 1);
807 lua_class_bind_data<T>* bdata = reinterpret_cast<lua_class_bind_data<T>*>(ptr);
808 bdata->fn = fn;
809 bdata->state = &state.get_master();
810 std::copy(fname.begin(), fname.end(), bdata->fname);
811 bdata->fname[fname.length()] = 0;
812 state.pushcclosure(class_bind_trampoline, 1);
813 state.rawset(-3);
814 state.pop(1);
817 * Bind multiple at once.
819 void bind_multi(lua_state& state, std::initializer_list<lua_class_binding<T>> list, void* doonce_key = NULL)
821 static char once_key;
822 if(state.do_once(doonce_key ? doonce_key : &once_key))
823 for(auto i : list)
824 bind(state, i.name, i.fn);
827 * Get a pointer to the object.
829 * Parameter state: The Lua state.
830 * Parameter arg: Argument index.
831 * Parameter fname: The name of function for error messages.
832 * Parameter optional: If true and argument is NIL or none, return NULL.
833 * Throws std::runtime_error: Wrong type.
835 static T* get(lua_state& state, int arg, const std::string& fname, bool optional = false)
836 throw(std::bad_alloc, std::runtime_error)
838 return objclass<T>()._get(state, arg, fname, optional);
842 * Identify if object is of this type.
844 * Parameter state: The Lua state.
845 * Parameter arg: Argument index.
846 * Returns: True if object is of specified type, false if not.
848 static bool is(lua_state& state, int arg) throw()
850 return objclass<T>()._is(state, arg);
853 * Get name of class.
855 static const std::string& get_name()
857 return objclass<T>().name;
860 * Format instance of this class as string.
862 static std::string print(lua_state& state, int index)
864 T* obj = get(state, index, "__internal_print");
865 return obj->print();
868 * Get a pin of object against Lua GC.
870 * Parameter state: The Lua state.
871 * Parameter arg: Argument index.
872 * Parameter fname: Name of function for error message purposes.
873 * Throws std::runtime_error: Wrong type.
875 static lua_obj_pin<T> pin(lua_state& state, int arg, const std::string& fname) throw(std::bad_alloc,
876 std::runtime_error)
878 return objclass<T>()._pin(state, arg, fname);
880 private:
881 static int dogc(lua_State* LS)
883 T* obj = reinterpret_cast<T*>(lua_touserdata(LS, 1));
884 obj->~T();
885 return 0;
888 static int newindex(lua_State* LS)
890 lua_pushstring(LS, "Writing metatables of classes is not allowed");
891 lua_error(LS);
892 return 0;
895 static int index(lua_State* LS)
897 lua_getmetatable(LS, 1);
898 lua_pushvalue(LS, 2);
899 lua_rawget(LS, -2);
900 return 1;
903 void load_metatable(lua_state& state)
905 again:
906 state.pushlightuserdata(this);
907 state.rawget(LUA_REGISTRYINDEX);
908 if(state.type(-1) == LUA_TNIL) {
909 state.pop(1);
910 state.pushlightuserdata(this);
911 state.newtable();
912 state.pushvalue(-1);
913 state.setmetatable(-2);
914 state.pushstring("__gc");
915 state.pushcfunction(&lua_class<T>::dogc);
916 state.rawset(-3);
917 state.pushstring("__newindex");
918 state.pushcfunction(&lua_class<T>::newindex);
919 state.rawset(-3);
920 state.pushstring("__index");
921 state.pushcfunction(&lua_class<T>::index);
922 state.rawset(-3);
923 state.rawset(LUA_REGISTRYINDEX);
924 goto again;
927 std::string name;
928 lua_class(const lua_class<T>&);
929 lua_class& operator=(const lua_class<T>&);
932 #define DECLARE_LUACLASS(x, X) template<> lua_class< x >& objclass() { static lua_class< x > clazz( X ); \
933 return clazz; }
936 * Function implemented in C++ exported to Lua.
938 class lua_function
940 public:
942 * Register function.
944 lua_function(lua_function_group& group, const std::string& name) throw(std::bad_alloc);
946 * Unregister function.
948 virtual ~lua_function() throw();
951 * Invoke function.
953 virtual int invoke(lua_state& L) = 0;
954 protected:
955 std::string fname;
956 lua_function_group& group;
960 * Register function pointer as lua function.
962 class function_ptr_luafun : public lua_function
964 public:
966 * Register.
968 function_ptr_luafun(lua_function_group& group, const std::string& name,
969 int (*_fn)(lua_state& L, const std::string& fname))
970 : lua_function(group, name)
972 fn = _fn;
975 * Invoke function.
977 int invoke(lua_state& L)
979 return fn(L, fname);
981 private:
982 int (*fn)(lua_state& L, const std::string& fname);
986 #endif