source: nscp/include/luna.h @ f029bc2

0.4.00.4.10.4.2
Last change on this file since f029bc2 was 1ff950c, checked in by Michael Medin <michael@…>, 4 years ago

Fixed build environment to work better (stand alone)

  • Property mode set to 100644
File size: 3.8 KB
Line 
1//extern "C" {
2#include "lua.h"
3#include "lauxlib.h"
4//}
5
6template <typename T> class Luna {
7  typedef struct { T *pT; } userdataType;
8public:
9  typedef int (T::*mfp)(lua_State *L);
10  typedef struct { const char *name; mfp mfunc; } RegType;
11
12  static void Register(lua_State *L) {
13    lua_newtable(L);
14    int methods = lua_gettop(L);
15
16    luaL_newmetatable(L, T::className);
17    int metatable = lua_gettop(L);
18
19    // store method table in globals so that
20    // scripts can add functions written in Lua.
21    lua_pushstring(L, T::className);
22    lua_pushvalue(L, methods);
23    lua_settable(L, LUA_GLOBALSINDEX);
24
25    lua_pushliteral(L, "__metatable");
26    lua_pushvalue(L, methods);
27    lua_settable(L, metatable);  // hide metatable from Lua getmetatable()
28
29    lua_pushliteral(L, "__index");
30    lua_pushvalue(L, methods);
31    lua_settable(L, metatable);
32
33    lua_pushliteral(L, "__tostring");
34    lua_pushcfunction(L, tostring_T);
35    lua_settable(L, metatable);
36
37    lua_pushliteral(L, "__gc");
38    lua_pushcfunction(L, gc_T);
39    lua_settable(L, metatable);
40
41    lua_newtable(L);                // mt for method table
42    int mt = lua_gettop(L);
43    lua_pushliteral(L, "__call");
44    lua_pushcfunction(L, new_T);
45    lua_pushliteral(L, "new");
46    lua_pushvalue(L, -2);           // dup new_T function
47    lua_settable(L, methods);       // add new_T to method table
48    lua_settable(L, mt);            // mt.__call = new_T
49    lua_setmetatable(L, methods);
50
51    // fill method table with methods from class T
52    for (RegType *l = T::methods; l->name; l++) {
53    /* edited by Snaily: shouldn't it be const RegType *l ... ? */
54      lua_pushstring(L, l->name);
55      lua_pushlightuserdata(L, (void*)l);
56      lua_pushcclosure(L, thunk, 1);
57      lua_settable(L, methods);
58    }
59
60    lua_pop(L, 2);  // drop metatable and method table
61  }
62
63  // get userdata from Lua stack and return pointer to T object
64  static T *check(lua_State *L, int narg) {
65    userdataType *ud =
66      static_cast<userdataType*>(luaL_checkudata(L, narg, T::className));
67    if(!ud) luaL_typerror(L, narg, T::className);
68    return ud->pT;  // pointer to T object
69  }
70
71private:
72  Luna();  // hide default constructor
73
74  // member function dispatcher
75  static int thunk(lua_State *L) {
76    // stack has userdata, followed by method args
77    T *obj = check(L, 1);  // get 'self', or if you prefer, 'this'
78    lua_remove(L, 1);  // remove self so member function args start at index 1
79    // get member function from upvalue
80    RegType *l = static_cast<RegType*>(lua_touserdata(L, lua_upvalueindex(1)));
81    return (obj->*(l->mfunc))(L);  // call member function
82  }
83
84  // create a new T object and
85  // push onto the Lua stack a userdata containing a pointer to T object
86  static int new_T(lua_State *L) {
87    lua_remove(L, 1);   // use classname:new(), instead of classname.new()
88    T *obj = new T(L);  // call constructor for T objects
89    userdataType *ud =
90      static_cast<userdataType*>(lua_newuserdata(L, sizeof(userdataType)));
91    ud->pT = obj;  // store pointer to object in userdata
92    luaL_getmetatable(L, T::className);  // lookup metatable in Lua registry
93    lua_setmetatable(L, -2);
94    return 1;  // userdata containing pointer to T object
95  }
96
97  // garbage collection metamethod
98  static int gc_T(lua_State *L) {
99    userdataType *ud = static_cast<userdataType*>(lua_touserdata(L, 1));
100    T *obj = ud->pT;
101    delete obj;  // call destructor for T objects
102    return 0;
103  }
104
105  static int tostring_T (lua_State *L) {
106    char buff[32];
107    userdataType *ud = static_cast<userdataType*>(lua_touserdata(L, 1));
108    T *obj = ud->pT;
109    sprintf(buff, "%p", obj);
110    lua_pushfstring(L, "%s (%s)", T::className, buff);
111    return 1;
112  }
113};
Note: See TracBrowser for help on using the repository browser.