最近在学习cocos2dx和Lua的交互,这里笔记下学习心得。
CONTENTS
备注:
1 作者对于Lua的使用较少,纯粹从使用出发,对它的理解较浅,可能有错误,还请路过的各位大牛多多指正。
2 本笔记代码部分参考cocos2dx2.2.3代码,代码版权归原作者所有。
3 由于作者时间,经验,能力有限,笔记可能不完整,以后随用随补充吧。
tolua_map.c:
文件内容较多,这里一点点笔记:
TOLUA_API void tolua_open (lua_State* L) { int top = lua_gettop(L); //先保存下当前堆栈的数目,这样返回时可以直接清理栈。 lua_pushstring(L,"tolua_opened"); //LUA_REGISTRYINDEX是一个伪索引,代表的是注册表所在的table,参考网址:【 http://116.62.110.235/blog/lua-basic-notes-save-status-in-c/ 】 lua_rawget(L,LUA_REGISTRYINDEX);//将 注册表["tolua_opened"]的值压入堆栈 if (!lua_isboolean(L,-1))//查一下注册表["tolua_opened"]是否为true,如果是true,说明已经打开过了,无需再次处理,直接返回。 {//如果没有打开过,就需要进入该if //更新注册表将注册表["tolua_opened"]设置为true lua_pushstring(L,"tolua_opened"); lua_pushboolean(L,1); lua_rawset(L,LUA_REGISTRYINDEX); /** create value root table */ //新建一个table添加到注册表中,即注册表[TOLUA_VALUE_ROOT] = new table; lua_pushstring(L, TOLUA_VALUE_ROOT); lua_newtable(L); lua_rawset(L, LUA_REGISTRYINDEX); #ifndef LUA_VERSION_NUM /* only prior to lua 5.1 */ /* create peer object table */ lua_pushstring(L, "tolua_peers"); lua_newtable(L); /* make weak key metatable for peers indexed by userdata object */ lua_newtable(L); lua_pushliteral(L, "__mode"); lua_pushliteral(L, "k"); lua_rawset(L, -3); /* stack: string peers mt */ lua_setmetatable(L, -2); /* stack: string peers */ lua_rawset(L,LUA_REGISTRYINDEX); #endif /* create object ptr -> udata mapping table */ lua_pushstring(L,"tolua_ubox"); lua_newtable(L); /* make weak value metatable for ubox table to allow userdata to be garbage-collected */ lua_newtable(L); lua_pushliteral(L, "__mode"); lua_pushliteral(L, "v"); //当前堆栈:tolua_box table1 table2 __mode v lua_rawset(L, -3); /* stack: string ubox mt *///当前堆栈:tolua_box table1 table2其中table2["__mode"] = "v" lua_setmetatable(L, -2); /* stack: string ubox */ //当前堆栈:tolua_box table1,table1的metatable是table2 lua_rawset(L,LUA_REGISTRYINDEX);//然后把table1也作为value放入map中,key是"tolua_box" //这样table1就是弱引用表,参考网址:http://116.62.110.235/blog/lua-basic-notes-weak-table/ // /* create object ptr -> class type mapping table */ // lua_pushstring(L, "tolua_ptr2type"); // lua_newtable(L); // lua_rawset(L, LUA_REGISTRYINDEX); //新建一个table添加到注册表中,即注册表["tolua_super"] = new table; lua_pushstring(L,"tolua_super"); lua_newtable(L); lua_rawset(L,LUA_REGISTRYINDEX); //新建一个table添加到注册表中,即注册表["tolua_gc"] = new table; lua_pushstring(L,"tolua_gc"); lua_newtable(L); lua_rawset(L,LUA_REGISTRYINDEX); /* create gc_event closure */ lua_pushstring(L, "tolua_gc_event"); lua_pushstring(L, "tolua_gc"); //当前堆栈:tolua_gc_event tolua_gc lua_rawget(L, LUA_REGISTRYINDEX);//当前堆栈:tolua_gc_event map["tolua_gc"] lua_pushstring(L, "tolua_super");//当前堆栈:tolua_gc_event map["tolua_gc"] tolua_super lua_rawget(L, LUA_REGISTRYINDEX);//当前堆栈:tolua_gc_event map["tolua_gc"] map["tolua_super"] lua_pushcclosure(L, class_gc_event, 2);//创建一个C closure,当前堆栈:tolua_gc_event,C closure lua_rawset(L, LUA_REGISTRYINDEX);//把C closure也作为value放入map中,key是"tolua_gc_event" //新建一个metatable,用来保存自定义的访问方式 tolua_newmetatable(L,"tolua_commonclass"); //新建一个匿名表 tolua_module(L,NULL,0); //把匿名表放到栈顶 tolua_beginmodule(L,NULL); //新建一个tolua表 tolua_module(L,"tolua",0); //把tolua表放到栈顶 tolua_beginmodule(L,"tolua"); //把下面的所有函数全部注册到tolua表中 tolua_function(L,"type",tolua_bnd_type); tolua_function(L,"takeownership",tolua_bnd_takeownership); tolua_function(L,"releaseownership",tolua_bnd_releaseownership); tolua_function(L,"cast",tolua_bnd_cast); tolua_function(L,"isnull",tolua_bnd_isnulluserdata); tolua_function(L,"inherit", tolua_bnd_inherit); #ifdef LUA_VERSION_NUM /* lua 5.1 */ tolua_function(L, "setpeer", tolua_bnd_setpeer); tolua_function(L, "getpeer", tolua_bnd_getpeer); #endif //清理栈 tolua_endmodule(L); tolua_endmodule(L); } lua_settop(L,top); } //创建一个metatable,用来自定义各种访问方式。 /* Create metatable * Create and register new metatable */ static int tolua_newmetatable (lua_State* L, const char* name) { int r = luaL_newmetatable(L,name); #ifdef LUA_VERSION_NUM /* only lua 5.1 */ if (r) { lua_pushvalue(L, -1); lua_pushstring(L, name); lua_settable(L, LUA_REGISTRYINDEX); /* reg[mt] = type_name */ }; #endif if (r) tolua_classevents(L); /* set meta events */ lua_pop(L,1); return r; } //将指定名称的table放入栈顶,如果名字为NULL,把全局变量表放入栈顶 /* Begin module * It pushes the module (or class) table on the stack */ TOLUA_API void tolua_beginmodule (lua_State* L, const char* name) { if (name) { lua_pushstring(L,name); lua_rawget(L,-2); } else lua_pushvalue(L,LUA_GLOBALSINDEX); } //简单的弹一下栈即可。 /* End module * It pops the module (or class) from the stack */ TOLUA_API void tolua_endmodule (lua_State* L) { lua_pop(L,1); } //新建一个table加入lua中。name为名称,此时默认当前堆栈顶部为全局变量表 TOLUA_API void tolua_module (lua_State* L, const char* name, int hasvar) { if (name) { /* tolua module */ lua_pushstring(L,name); lua_rawget(L,-2);//先查一下当前环境中有没有以name命名的table if (!lua_istable(L,-1)) /* check if module already exists */ {//如果没有,就新建一个table,命名为name lua_pop(L,1); lua_newtable(L); lua_pushstring(L,name); lua_pushvalue(L,-2); //将table命名为name,放入全局变量表中 lua_rawset(L,-4); /* assing module into module */ } } else { //如果名字为空,说明放入全局变量表。 /* global table */ lua_pushvalue(L,LUA_GLOBALSINDEX); } //如果有自定义变量,那就要修改table的默认访问方式,即metatable if (hasvar) { if (!tolua_ismodulemetatable(L)) /* check if it already has a module metatable */ { /* create metatable to get/set C/C++ variable */ lua_newtable(L); tolua_moduleevents(L); if (lua_getmetatable(L,-2)) lua_setmetatable(L,-2); /* set old metatable as metatable of metatable */ lua_setmetatable(L,-2); } } lua_pop(L,1); /* pop module */ } //将C函数注册到当前的table中,注意这里栈顶应该是一个table,然后调用该方法 /* Map function * It assigns a function into the current module (or class) */ TOLUA_API void tolua_function (lua_State* L, const char* name, lua_CFunction func) { //当前堆栈: table lua_pushstring(L,name); lua_pushcfunction(L,func); //当前堆栈 table, name, func lua_rawset(L,-3); //当前堆栈:table //table["name"] = func }
//注册一个用户类,这里同时注册该类型的常量类。 //实际工作其实就是在注册表中注册一个metatable,绑定了各种自定义的访问方法。 /* Register a usertype * It creates the correspoding metatable in the registry, for both 'type' and 'const type'. * It maps 'const type' as being also a 'type' */ TOLUA_API void tolua_usertype (lua_State* L, const char* type) { char ctype[128] = "const "; strncat(ctype,type,120); /* create both metatables */ //创建两个metatable if (tolua_newmetatable(L,ctype) && tolua_newmetatable(L,type)) mapsuper(L,type,ctype); /* 'type' is also a 'const type' */ } //把base关联的metatable复制一份放到name中 /* Map super classes * It sets 'name' as being also a 'base', mapping all super classes of 'base' in 'name' */ static void mapsuper (lua_State* L, const char* name, const char* base) { /* push registry.super */ lua_pushstring(L,"tolua_super"); lua_rawget(L,LUA_REGISTRYINDEX); /* stack: super */ luaL_getmetatable(L,name); /* stack: super mt */ lua_rawget(L,-2); /* stack: super table */ //首先看下tolua_super表中有没有以metatableA为key的表B 。 //即 metatableA = 注册表["name"] 表B = tolua_super[metatableA] //如果没有,就新建一个(进入if) if (lua_isnil(L,-1)) { //新建一个普通表作为value,metatableA为key,插入到tolua_supe中 /* create table */ lua_pop(L,1); lua_newtable(L); /* stack: super table */ luaL_getmetatable(L,name); /* stack: super table mt */ lua_pushvalue(L,-2); /* stack: super table mt table */ lua_rawset(L,-4); /* stack: super table */ } //设置 表B["base"] = 1 /* set base as super class */ lua_pushstring(L,base); lua_pushboolean(L,1); lua_rawset(L,-3); /* stack: super table */ /* set all super class of base as super class of name */ luaL_getmetatable(L,base); /* stack: super table base_mt */ lua_rawget(L,-3); /* stack: super table base_table */ //首先看下tolua_super表中有没有以metatableB为key的表D 。 //即 metatableB = 注册表["base"] 表D = tolua_super[metatableB] //如果有这个表D,进入下面的if if (lua_istable(L,-1)) { //把表D中的所有内容全部复制到表B中。 //参考网址:http://www.codingnow.com/2000/download/lua_manual.html#lua_next /* traverse base table */ lua_pushnil(L); /* first key */ while (lua_next(L,-2) != 0) { /* stack: ... base_table key value */ lua_pushvalue(L,-2); /* stack: ... base_table key value key */ lua_insert(L,-2); /* stack: ... base_table key key value */ lua_rawset(L,-5); /* stack: ... base_table key */ } } //清理栈 lua_pop(L,3); /* stack: <empty> */ } //添加一个基类 /* Add base * It adds additional base classes to a class (for multiple inheritance) * (not for now) */ TOLUA_API void tolua_addbase(lua_State* L, char* name, char* base) { char cname[128] = "const "; char cbase[128] = "const "; strncat(cname,name,120); strncat(cbase,base,120); mapsuper(L,cname,cbase); mapsuper(L,name,base); };
发表评论