00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifndef LUGRE_LUABIND_DIRECT_H
00025 #define LUGRE_LUABIND_DIRECT_H
00026 #include <vector>
00027 #include <string>
00028 #include <stdexcept>
00029
00030 extern "C" {
00031 #include "lua.h"
00032 #include "lauxlib.h"
00033 #include "lualib.h"
00034 }
00035
00036 namespace Lugre {
00037
00038
00039 struct luaL_reg make_luaL_reg (const char *name,lua_CFunction func);
00040
00041
00042
00043
00044 #define LUABIND_QUICKWRAP_STATIC(methodname,code) \
00045 { class cTempClass : public cLuaBindDirectQuickWrapHelper { public: \
00046 static int methodname (lua_State *L) { PROFILE code return 0; }\
00047 }; \
00048 lua_register(L,#methodname,&cTempClass::methodname); \
00049 }
00050 #define LUABIND_QUICKWRAP(methodname,code) \
00051 { class cTempClass : public cLuaBindDirectQuickWrapHelper { public: \
00052 static int methodname (lua_State *L) { PROFILE code return 0; }\
00053 }; \
00054 mlMethod.push_back(make_luaL_reg(#methodname,&cTempClass::methodname)); \
00055 }
00056
00057
00058
00059
00060
00061
00062
00063
00064 #define LUABIND_DIRECTWRAP_RETURN_ONE_ALTNAME(returnpushfun,newname,methodname,paramcode) LUABIND_QUICKWRAP( newname, { return returnpushfun(L,GetSelf(L).methodname paramcode ); });
00065 #define LUABIND_DIRECTWRAP_RETURN_VOID_ALTNAME(newname,methodname,paramcode) LUABIND_QUICKWRAP( newname, { GetSelf(L).methodname paramcode ; });
00066
00067 #define LUABIND_DIRECTWRAP_RETURN_ONE_NAMEADD(returnpushfun,methodname,nameadd,paramcode) LUABIND_DIRECTWRAP_RETURN_ONE_ALTNAME(returnpushfun,methodname##nameadd,methodname,paramcode)
00068 #define LUABIND_DIRECTWRAP_RETURN_VOID_NAMEADD(methodname,nameadd,paramcode) LUABIND_DIRECTWRAP_RETURN_VOID_ALTNAME(methodname##nameadd,methodname,paramcode)
00069
00070 #define LUABIND_DIRECTWRAP_RETURN_ONE(returnpushfun,methodname,paramcode) LUABIND_DIRECTWRAP_RETURN_ONE_ALTNAME(returnpushfun,methodname,methodname,paramcode)
00071 #define LUABIND_DIRECTWRAP_RETURN_VOID(methodname,paramcode) LUABIND_DIRECTWRAP_RETURN_VOID_ALTNAME(methodname,methodname,paramcode)
00072
00073
00074 #define LUABIND_DIRECTWRAP_BASECLASS(classname) RegisterBaseClass(cLuaBindDirect<classname>::GetSingletonPtr(),#classname);
00075
00076 #define LUABIND_PrefixConstant(prefix,name) cScripting::SetGlobal(L,#name,prefix::name);
00077
00078
00079 #define LUABIND_DIRECTWRAP_HELPER_ENUM(prefix,name) \
00080 static inline prefix::name Param##name (lua_State *L,int i) { return (prefix::name)ParamInt(L,i); }
00081 #define LUABIND_DIRECTWRAP_HELPER_OBJECT(mytype,name) \
00082 static inline mytype& ParamByRef##name (lua_State *L,int i) { return *cLuaBindDirect<mytype>::checkudata_alive(L,i); } \
00083 static inline mytype* Param##name (lua_State *L,int i) { return cLuaBindDirect<mytype>::checkudata_alive(L,i); } \
00084 static inline int Push##name (lua_State *L,mytype* v) { return cLuaBindDirect<mytype>::CreateUData(L,v); }
00085 #define LUABIND_DIRECTWRAP_HELPER_OBJECT_PREFIX(prefix,mytypename) LUABIND_DIRECTWRAP_HELPER_OBJECT(prefix::mytypename,mytypename)
00086
00087 #define LUABIND_DIRECTWRAP_HELPER_PUSH_COPY(prefix,mytype) \
00088 static inline int PushCopy##mytype (lua_State *L,prefix::mytype& v) { return cLuaBindDirect<prefix::mytype>::CreateUData(L,new prefix::mytype(v)); }
00089
00091 class cLuaBindDirectQuickWrapHelper { public:
00092 static inline bool ParamIsSet (lua_State *L,int i) { return lua_gettop(L) >= i && !lua_isnil(L,i); }
00093
00094 static inline std::string ParamString (lua_State *L,int i) { return std::string(luaL_checkstring(L,i)); }
00095 static inline int ParamInt (lua_State *L,int i) { return luaL_checkint(L,i); }
00096 static inline float ParamFloat (lua_State *L,int i) { return luaL_checknumber(L,i); }
00097 static inline lua_Number ParamNumber (lua_State *L,int i) { return luaL_checknumber(L,i); }
00098 static inline bool ParamBool (lua_State *L,int i) { return lua_isboolean(L,i) ? lua_toboolean(L,i) : luaL_checkint(L,i); }
00099 static inline void* ParamPointer (lua_State *L,int i) {
00100 void** p = (void**)lua_touserdata(L,i);
00101 if (p == 0 && !lua_isuserdata(L,i)) luaL_typerror(L, i, lua_typename(L,LUA_TUSERDATA));
00102 return *p;
00103 }
00104
00105 static inline void ParamFloatArr (lua_State *L,int i,float* arr,int len) {
00106 if (!lua_istable(L,i)) luaL_typerror(L, i, lua_typename(L,LUA_TTABLE));
00107 for (int k=0;k<len;++k) {
00108 lua_rawgeti(L,i,k+1);
00109 arr[k] = lua_tonumber(L,-1);
00110 lua_pop(L,1);
00111 }
00112 }
00113
00114 static inline std::string ParamStringDefault (lua_State *L,int i,std::string d) { return ParamIsSet(L,i) ? ParamString(L,i) : d; }
00115 static inline int ParamIntDefault (lua_State *L,int i,int d) { return ParamIsSet(L,i) ? ParamInt(L,i) : d; }
00116 static inline float ParamFloatDefault (lua_State *L,int i,float d) { return ParamIsSet(L,i) ? ParamFloat(L,i) : d; }
00117 static inline lua_Number ParamNumberDefault (lua_State *L,int i,lua_Number d) { return ParamIsSet(L,i) ? ParamNumber(L,i) : d; }
00118 static inline bool ParamBoolDefault (lua_State *L,int i,bool d) { return ParamIsSet(L,i) ? ParamBool(L,i) : d; }
00119 static inline void* ParamPointerDefault (lua_State *L,int i,void* d) { return ParamIsSet(L,i) ? ParamPointer(L,i) : d; }
00120
00121 static inline int PushBool (lua_State *L,bool v) { lua_pushboolean(L,v); return 1; }
00122 static inline int PushString (lua_State *L,const char* v) { lua_pushstring(L,v); return 1; }
00123 static inline int PushString (lua_State *L,std::string v) { lua_pushstring(L,v.c_str()); return 1; }
00124 static inline int PushNumber (lua_State *L,lua_Number v) { lua_pushnumber(L,v); return 1; }
00125 static inline int PushNil (lua_State *L) { lua_pushnil(L); return 1; }
00126 static inline int PushPointer (lua_State *L,void* v) { lua_pushlightuserdata(L,v); return 1; }
00127 };
00128
00129
00130
00131 class cLuaBindDirectBase : public cLuaBindDirectQuickWrapHelper { public:
00132 std::vector<struct luaL_reg> mlMethod;
00133 };
00134
00135 template<class _T> class cLuaBindDirect : public cLuaBindDirectBase { public:
00136
00138 virtual const char* GetLuaTypeName () = 0;
00139
00141 virtual void RegisterMethods (lua_State *L) = 0;
00142
00143 void RegisterBaseClass (cLuaBindDirectBase* pBase,const char* szParentClassName) {
00144 if (!pBase) { throw std::runtime_error(strprintf("luabinddirect : failed to load baseclass '%s' of '%s', make sure the baseclass is registered first",szParentClassName,GetLuaTypeName())); }
00145 mlMethod.insert(mlMethod.begin(),pBase->mlMethod.begin(),pBase->mlMethod.end());
00146 }
00147
00148 static inline int CreateUData (lua_State *L,_T* target) { PROFILE
00149 if (!target) return 0;
00150
00151
00152 void** o = (void**)lua_newuserdata(L,sizeof(void*));
00153 *o = target;
00154
00155
00156
00157 luaL_getmetatable(L,GetSingletonPtr()->GetLuaTypeName());
00158 lua_setmetatable(L,-2);
00159 return 1;
00160 }
00161
00163 static inline void RemoveMetaTable (lua_State *L,int i=1) { PROFILE
00164 lua_pushnil(L);
00165 lua_setmetatable(L,i);
00166 }
00167
00169 static inline _T& GetSelf (lua_State *L,int i=1) { return *(_T*)(*(void**)lua_touserdata(L,i)); }
00170 static inline _T* checkudata (lua_State *L,int i=1) { return (_T*)(*(void**)lua_touserdata(L,i)); }
00171 static inline _T* checkudata_alive (lua_State *L,int i=1) { return (_T*)(*(void**)lua_touserdata(L,i)); }
00172
00173 void LuaRegister (lua_State *L) { PROFILE
00174 mlMethod.clear();
00175
00176
00177
00178
00179
00180
00181
00182
00183 RegisterMethods(L);
00184
00185
00186
00187 int res = luaL_newmetatable(L,GetSingletonPtr()->GetLuaTypeName());
00188 if (res != 1) { printf("cLuaBindDirect:LuaRegister : classname already used\n"); }
00189
00190
00191 lua_newtable(L);
00192 for (int i=0;i<mlMethod.size();++i) {
00193 lua_pushcfunction(L,mlMethod[i].func);
00194 lua_setfield(L,-2,mlMethod[i].name);
00195 }
00196
00197
00198 lua_setfield(L,-2,"__index");
00199 lua_pop(L,1);
00200 }
00201
00202
00203
00204 virtual ~cLuaBindDirect(){};
00205
00206 static cLuaBindDirect<_T>* GetSingletonPtr (cLuaBindDirect<_T>* prototype=0) { PROFILE
00207 static cLuaBindDirect<_T>* pSingleton = 0;
00208 if (pSingleton) return pSingleton;
00209 pSingleton = prototype;
00210 assert(pSingleton);
00211 return pSingleton;
00212 }
00213 };
00214
00215
00216 };
00217
00218 #endif