Main Page | Namespace List | Class Hierarchy | Class List | File List | Namespace Members | Class Members | File Members

LuaBinding.h

Go to the documentation of this file.
00001 /* Based on Lua Wiki example: http://lua-users.org/wiki/SimplerCppBinding 00002 * Modified by Chris. 00003 */ 00004 00005 extern "C" 00006 { 00007 #include <lua.h> 00008 #include <lauxlib.h> 00009 } 00010 00011 #include "LuaManager.h" 00012 00013 00014 #define SArg(n) (luaL_checkstring(L,n)) 00015 #define IArg(n) (luaL_checkint(L,n)) 00016 #define BArg(n) (!!IArg(n)) 00017 #define FArg(n) ((float) luaL_checknumber(L,n)) 00018 00019 00020 #define LUA_REGISTER_CLASS( T ) \ 00021 class Lua##T { \ 00022 public: \ 00023 Lua##T() { LUA->Register( Register ); } \ 00024 static const char className[]; \ 00025 static Luna<T,Lua##T>::RegType methods[]; \ 00026 static void Register( lua_State* L ) { \ 00027 Luna<T,Lua##T>::Register(L); \ 00028 } \ 00029 LUA_##T##_METHODS( T ) \ 00030 }; \ 00031 static Lua##T registera; \ 00032 const char Lua##T::className[] = #T; \ 00033 Luna<T,Lua##T>::RegType Lua##T::methods[] = { \ 00034 LUA_##T##_METHODS_MAP( T ) \ 00035 {0,0} \ 00036 }; 00037 #define LUA_METHOD_MAP( T, Method ) { #Method, Lua##T::Method }, 00038 00039 00040 template <typename T, typename TInfo> class Luna { 00041 typedef struct { T *pT; } userdataType; 00042 public: 00043 typedef int (*mfp)(T *p, lua_State *L); 00044 typedef struct { const char *name; mfp mfunc; } RegType; 00045 00046 static void Register(lua_State *L) { 00047 lua_newtable(L); 00048 int methods = lua_gettop(L); 00049 00050 luaL_newmetatable(L, TInfo::className); 00051 int metatable = lua_gettop(L); 00052 00053 // store method table in globals so that 00054 // scripts can add functions written in Lua. 00055 lua_pushstring(L, TInfo::className); 00056 lua_pushvalue(L, methods); 00057 lua_settable(L, LUA_GLOBALSINDEX); 00058 00059 lua_pushliteral(L, "__metatable"); 00060 lua_pushvalue(L, methods); 00061 lua_settable(L, metatable); // hide metatable from Lua getmetatable() 00062 00063 lua_pushliteral(L, "__index"); 00064 lua_pushvalue(L, methods); 00065 lua_settable(L, metatable); 00066 00067 lua_pushliteral(L, "__tostring"); 00068 lua_pushcfunction(L, tostring_T); 00069 lua_settable(L, metatable); 00070 00071 // fill method table with methods from class T 00072 for (RegType *l = TInfo::methods; l->name; l++) { 00073 lua_pushstring(L, l->name); 00074 lua_pushlightuserdata(L, (void*)l); 00075 lua_pushcclosure(L, thunk, 1); 00076 lua_settable(L, methods); 00077 } 00078 00079 lua_pop(L, 2); // drop metatable and method table 00080 } 00081 00082 // get userdata from Lua stack and return pointer to T object 00083 static T *check(lua_State *L, int narg) { 00084 userdataType *ud = 00085 static_cast<userdataType*>(luaL_checkudata(L, narg, TInfo::className)); 00086 if(!ud) luaL_typerror(L, narg, TInfo::className); 00087 return ud->pT; // pointer to T object 00088 } 00089 00090 private: 00091 Luna(); // hide default constructor 00092 00093 // member function dispatcher 00094 static int thunk(lua_State *L) { 00095 // stack has userdata, followed by method args 00096 T *obj = check(L, 1); // get 'self', or if you prefer, 'this' 00097 lua_remove(L, 1); // remove self so member function args start at index 1 00098 // get member function from upvalue 00099 RegType *l = static_cast<RegType*>(lua_touserdata(L, lua_upvalueindex(1))); 00100 return (*(l->mfunc))(obj,L); // call member function 00101 } 00102 00103 public: 00104 // create a new T object and 00105 // push onto the Lua stack a userdata containing a pointer to T object 00106 static int Push(lua_State *L, T* p ) { 00107 userdataType *ud = static_cast<userdataType*>(lua_newuserdata(L, sizeof(userdataType))); 00108 ud->pT = p; // store pointer to object in userdata 00109 luaL_getmetatable(L, TInfo::className); // lookup metatable in Lua registry 00110 lua_setmetatable(L, -2); 00111 return 1; // userdata containing pointer to T object 00112 } 00113 00114 private: 00115 00116 static int tostring_T (lua_State *L) { 00117 char buff[32]; 00118 userdataType *ud = static_cast<userdataType*>(lua_touserdata(L, 1)); 00119 T *obj = ud->pT; 00120 sprintf(buff, "%p", obj); 00121 lua_pushfstring(L, "%s (%s)", TInfo::className, buff); 00122 return 1; 00123 } 00124 }; 00125 00126 /* 00127 * (c) 2001-2005 lua-users.org, Chris Danford 00128 * All rights reserved. 00129 * 00130 * Permission is hereby granted, free of charge, to any person obtaining a 00131 * copy of this software and associated documentation files (the 00132 * "Software"), to deal in the Software without restriction, including 00133 * without limitation the rights to use, copy, modify, merge, publish, 00134 * distribute, and/or sell copies of the Software, and to permit persons to 00135 * whom the Software is furnished to do so, provided that the above 00136 * copyright notice(s) and this permission notice appear in all copies of 00137 * the Software and that both the above copyright notice(s) and this 00138 * permission notice appear in supporting documentation. 00139 * 00140 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 00141 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 00142 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF 00143 * THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS 00144 * INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT 00145 * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS 00146 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 00147 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 00148 * PERFORMANCE OF THIS SOFTWARE. 00149 */

Generated on Thu Jan 27 20:57:23 2005 for StepMania by doxygen 1.3.7