UGDK
src/module/luaproxy.h
Go to the documentation of this file.
00001 
00002 #ifndef MODULE_LUAPROXY_H_
00003 #define MODULE_LUAPROXY_H_
00004 
00005 #include <ugdk/script/languages/lua/header.h>
00006 #include <ugdk/script/languages/lua/state.h>
00007 #include <ugdk/script/scriptmanager.h>
00008 #include <ugdk/script/virtualobj.h>
00009 #include <ugdk/script/virtualdata.h>
00010 
00011 namespace ugdk {
00012 namespace script {
00013 namespace lua {
00014 
00015 static int ClassGet(lua_State* L) {
00016     /*  there should be 2 params passed in
00017       (1) userdata (not the meta table)
00018       (2) string name of the attribute
00019     */
00020   assert(lua_isuserdata(L,-2) || lua_istable(L,-2));  /* just in case */
00021   lua_getmetatable(L,-2);    /* get the meta table */
00022   assert(lua_istable(L,-1));  /* just in case */
00023   SWIG_Lua_get_table(L,".get"); /* find the .get table */
00024   assert(lua_istable(L,-1));  /* just in case */
00025   /* look for the key in the .get table */
00026   lua_pushvalue(L,2);  /* key */
00027   lua_rawget(L,-2);
00028   lua_remove(L,-2); /* stack tidy, remove .get table */
00029   if (lua_iscfunction(L,-1))
00030   {  /* found it so call the fn & return its value */
00031     lua_pushvalue(L,1);  /* the userdata */
00032     lua_call(L,1,1);  /* 1 value in (userdata),1 out (result) */
00033     lua_remove(L,-2); /* stack tidy, remove metatable */
00034     return 1;
00035   }
00036   lua_pop(L,1);  /* remove whatever was there */
00037   /* ok, so try the .fn table */
00038   SWIG_Lua_get_table(L,".fn"); /* find the .get table */
00039   assert(lua_istable(L,-1));  /* just in case */
00040   lua_pushvalue(L,2);  /* key */
00041   lua_rawget(L,-2);  /* look for the fn */
00042   lua_remove(L,-2); /* stack tidy, remove .fn table */
00043   if (lua_isfunction(L,-1)) /* note: if its a C function or lua function */
00044   {  /* found it so return the fn & let lua call it */
00045     lua_remove(L,-2); /* stack tidy, remove metatable */
00046     return 1;
00047   }
00048   lua_pop(L,1);  /* remove whatever was there */
00049   /* NEW: looks for the __getitem() fn
00050   this is a user provided get fn */
00051   SWIG_Lua_get_table(L,"__getitem"); /* find the __getitem fn */
00052   if (lua_iscfunction(L,-1))  /* if its there */
00053   {  /* found it so call the fn & return its value */
00054     lua_pushvalue(L,1);  /* the userdata */
00055     lua_pushvalue(L,2);  /* the parameter */
00056     lua_call(L,2,1);  /* 2 value in (userdata),1 out (result) */
00057     lua_remove(L,-2); /* stack tidy, remove metatable */
00058     return 1;
00059   }
00060   return 0;  /* sorry not known */
00061 }
00062 
00063 /* the class.set method, performs the lookup of class attributes */
00064 static int  ClassSet(lua_State* L) {
00065 /*  there should be 3 params passed in
00066   (1) table (not the meta table)
00067   (2) string name of the attribute
00068   (3) any for the new value
00069 printf("SWIG_Lua_class_set %p(%s) '%s' %p(%s)\n",
00070       lua_topointer(L,1),lua_typename(L,lua_type(L,1)),
00071       lua_tostring(L,2),
00072       lua_topointer(L,3),lua_typename(L,lua_type(L,3)));*/
00073 
00074   assert(lua_isuserdata(L,1) || lua_istable(L,1));  /* just in case */
00075   lua_getmetatable(L,1);    /* get the meta table */
00076   assert(lua_istable(L,-1));  /* just in case */
00077 
00078   SWIG_Lua_get_table(L,".set"); /* find the .set table */
00079   if (lua_istable(L,-1))
00080   {
00081     /* look for the key in the .set table */
00082     lua_pushvalue(L,2);  /* key */
00083     lua_rawget(L,-2);
00084     if (lua_iscfunction(L,-1))
00085     {  /* found it so call the fn & return its value */
00086       lua_pushvalue(L,1);  /* userdata */
00087       lua_pushvalue(L,3);  /* value */
00088       lua_call(L,2,0);
00089       return 0;
00090     }
00091     lua_pop(L,1);  /* remove the value */
00092   }
00093   lua_pop(L,1);  /* remove the value .set table */
00094   /* NEW: looks for the __setitem() fn
00095   this is a user provided set fn */
00096   SWIG_Lua_get_table(L,"__setitem"); /* find the fn */
00097   if (lua_iscfunction(L,-1))  /* if its there */
00098   {  /* found it so call the fn & return its value */
00099     lua_pushvalue(L,1);  /* the userdata */
00100     lua_pushvalue(L,2);  /* the parameter */
00101     lua_pushvalue(L,3);  /* the value */
00102     lua_call(L,3,0);  /* 3 values in ,0 out */
00103     lua_remove(L,-2); /* stack tidy, remove metatable */
00104     return 1;
00105   }
00106   // final case... just put it in the goddamn table, dude.
00107   lua_settop(L, 3); // go back to original stack
00108   if (lua_istable(L, 1))
00109       lua_rawset(L, 1);
00110   return 0;
00111 }
00112 
00113 static void ExportMetamethods (lua_State *L) {
00114     lua_getfield(L, LUA_GLOBALSINDEX, "UGDK_proxymethods");
00115     if (lua_istable(L,-1)) // someone already made it
00116         return;
00117     lua_createtable(L, 0, 2);
00118     lua_pushcclosure(L, ClassGet, 0);
00119     lua_setfield(L, -2, "getter");
00120     lua_pushcclosure(L, ClassSet, 0);
00121     lua_setfield(L, -2, "setter");
00122     lua_setfield(L, LUA_GLOBALSINDEX, "UGDK_proxymethods");
00123 }
00124 
00125 } /* namespace lua */
00126 } /* namespace script */
00127 } /* namespace ugdk */
00128 
00129 #endif /* MODULE_LUAPROXY_H_ */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines