最近在学习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);
};
发表评论