tolua++的一些api的
来源:互联网 发布:unity3d ios 模拟器 编辑:程序博客网 时间:2024/06/05 20:23
1:TOLUA_API void tolua_usertype (lua_State* L, const char* type)
作用:注册type类型的用户类,建立table-->type和type-->table的双向映射。
源代码和分析:
TOLUA_API void tolua_usertype (lua_State* L, const char* type){ char ctype[128] = "const "; strncat(ctype,type,120); /* create both metatables *///同时创建type类型和const type类型。并且const type为type的父类 if (tolua_newmetatable(L,ctype) && tolua_newmetatable(L,type)) mapsuper(L,type,ctype); /* 'type' is also a 'const type' */}
static int tolua_newmetatable (lua_State* L, const char* name){//创建一个table,并且在注册表中与name对应 reg[name] = mt int r = luaL_newmetatable(L,name);#ifdef LUA_VERSION_NUM /* only lua 5.1 */ if (r) { lua_pushvalue(L, -1); lua_pushstring(L, name);
//同时建立反向映射,这样就可以根据一个name对应的用户类型变量找到该变量的类名//将类名和某一种类名进行比较,就可以判断是不是某种类型。
lua_settable(L, LUA_REGISTRYINDEX); /* reg[mt] = type_name */ };#endif if (r) tolua_classevents(L); /* set meta events */ //向metatable中注册各种元方法,比如:__index,__newindex,__add等等 lua_pop(L,1); return r;}
2:static void mapsuper (lua_State* L, const char* name, const char* base)
作用:将base设置成name的基类,并且将base的全部父类也设置成name的基类
源代码和分析:
static void mapsuper (lua_State* L, const char* name, const char* base){ /* push registry.super */ lua_pushstring(L,"tolua_super");//-1 lua_rawget(L,LUA_REGISTRYINDEX); /* stack: super */ luaL_getmetatable(L,name); /* stack: super mt */ lua_rawget(L,-2); /* stack: super table */ if (lua_isnil(L,-1)) { /* 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 */
<span style="white-space:pre"></span>//tolua_super在 注册表中也对应一张表,表的内容为:<span style="white-space:pre"></span>//table[key] = value,key是:用户类型对应的表,value是:一张表 <span style="white-space:pre"></span>//以name = cc.Node为例,全局表:G_Table,tolua_super对应的表:Super_Table <span style="white-space:pre"></span>//ta = G_Table[name] Super_Table[ta] = tb(tb就是name在Super_Table中对应的表),它的具体数据看下面<span style="white-space:pre"></span>//我们简称tb为name的父类表 }//开始往tb中塞数据 /* 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 */
//获取base对应的父类表,接下来就是遍历父类表吧 lua_rawget(L,-3); /* stack: super table base_table */ if (lua_istable(L,-1)) { /* 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> */}
3:TOLUA_API void tolua_cclass (lua_State* L, const char* lname, const char* name, const char* base, lua_CFunction col)
作用:并且设置该lua类的父类,lname:我的理解是该lua类的模块名,name:类名, base:父类名
例子:cc.Node的表注册结构:
global_table
-cc_table
-Node_table
源码和分析:
TOLUA_API void tolua_cclass (lua_State* L, const char* lname, const char* name, const char* base, lua_CFunction col){ char cname[128] = "const "; char cbase[128] = "const "; strncat(cname,name,120); strncat(cbase,base,120); mapinheritance(L,name,base);//设置base表为name表的元表,继承啊!!这样才可以访问到父类的成员。还有创建tolua_ubox表。 mapinheritance(L,cname,name); mapsuper(L,cname,cbase);//拷贝父类 mapsuper(L,name,base); lua_pushstring(L,lname); push_collector(L, name, col);//设置表的.collector函数 /* luaL_getmetatable(L,name); lua_pushstring(L,".collector"); lua_pushcfunction(L,col); lua_rawset(L,-3); */ luaL_getmetatable(L,name);//向当前的模块进行注册 如果当前的模块名是cc,lname为Node,那么cc_module_table[lname] = name_table lua_rawset(L,-3); /* assign class metatable to module */ /* now we also need to store the collector table for the const instances of the class */ push_collector(L, cname, col); /* luaL_getmetatable(L,cname); lua_pushstring(L,".collector"); lua_pushcfunction(L,col); lua_rawset(L,-3); lua_pop(L,1); */}
4:TOLUA_API void tolua_module (lua_State* L, const char* name, int hasvar)
作用:尝试创建一个模块。
实现方式:以name为key,模块表为value放入到父模块表中。如果存在name的表,那么不做操作,否则创建一个呗。一般来说在tolua_cclass中已经注册过了。
源码和分析:
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在当前模块表中是否进行了注册 if (!lua_istable(L,-1)) /* check if module already exists */ {//没有注册过,new一个 lua_pop(L,1); lua_newtable(L); lua_pushstring(L,name); lua_pushvalue(L,-2);//注册到当前模块表中去 lua_rawset(L,-4); /* assing module into module */ } } else { /* global table *///这个是全局表,会被最先放入到栈中去。因为它是所有其他根模块的进行注册的地方 lua_pushvalue(L,LUA_GLOBALSINDEX); } ....... lua_pop(L,1); /* pop module */}
5:TOLUA_API void tolua_beginmodule (lua_State* L, const char* name)
作用:顾名思义,开始一个模块
实现方式:将name对应的模块表放入到栈顶。
源码和分析:(这个貌似不需要解释吧,很简单)
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);}
6:int lua_isusertype (lua_State* L, int lo, const char* type)
源码和分析:(不多说,都在代码中)
//作用:判断在lua栈中的lo位置的类型是不是type(不要忘了父类哟!!)。//type:要比较的类型名int lua_isusertype (lua_State* L, int lo, const char* type){
if (!lua_isuserdata(L,lo)) { if (!push_table_instance(L, lo)) { return 0; }; }; { /* check if it is of the same type */ int r; const char *tn;//获取到lo位置的userdata的metatable表 if (lua_getmetatable(L,lo)) /* if metatable? */ {//当创建类的时候,会进行双向映射,所以可以根据table获取类名 lua_rawget(L,LUA_REGISTRYINDEX); /* get registry[mt] */ tn = lua_tostring(L,-1); r = tn && (strcmp(tn,type) == 0);//如果对应的类名就是type,那么loc位置的userdata就是对应type类型 lua_pop(L, 1); if (r) return 1; else {//不要忘了所有的父类哟!!还记得父类是怎么实现的么,详细请参考:tolua_map.mapsuper() /* check if it is a specialized class */ lua_pushstring(L,"tolua_super"); lua_rawget(L,LUA_REGISTRYINDEX); /* get super */ lua_getmetatable(L,lo); lua_rawget(L,-2); /* get super[mt] */ if (lua_istable(L,-1)) { int b; lua_pushstring(L,type); lua_rawget(L,-2); /* get super[mt][type] */ b = lua_toboolean(L,-1); lua_pop(L,3); if (b) return 1; } } } } return 0;}
大概流程是这样的:先获取该位置的userdata的metatable,再根据注册表拿到它对应的类型,判断该类型是不是type或者type是它的父类。
7:static void mapinheritance (lua_State* L, const char* name, const char* base)
static void mapinheritance (lua_State* L, const char* name, const char* base){ /* set metatable inheritance */ luaL_getmetatable(L,name); if (base && *base) luaL_getmetatable(L,base); else { if (lua_getmetatable(L, -1)) { /* already has a mt, we don't overwrite it */ lua_pop(L, 2); return; }; luaL_getmetatable(L,"tolua_commonclass"); }; set_ubox(L); lua_setmetatable(L,-2); lua_pop(L,1);}
这个比较简单,就是两个功能。提前说一下:set_ubox是设置该表的tolua_ubox表,具体tolua_ubox数据是什么样的下面再讲。还有就是设置name表的metatable为base表。
8:static void set_ubox(lua_State* L)
static void set_ubox(lua_State* L) { /* mt basemt */ if (!lua_isnil(L, -1)) { lua_pushstring(L, "tolua_ubox"); lua_rawget(L,-2);//获取base表中的tolua_ubox值 } else { lua_pushnil(L); }; /* mt basemt base_ubox */ if (!lua_isnil(L,-1)) {//得到父类tolua_ubox表 lua_pushstring(L, "tolua_ubox"); lua_insert(L, -2); /* mt basemt key ubox */ lua_rawset(L,-4); /* (mt with ubox) basemt */ } else { /* mt basemt nil *///如果不存在base或者base中没有tolua_ubox,那么为子类创建一个弱引用的tolua_ubox表 lua_pop(L, 1); 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");//值为弱引用 lua_rawset(L, -3); /* stack: string ubox mt */ lua_setmetatable(L, -2); /* stack:mt basemt string ubox */ lua_rawset(L,-4); };};
创建tolua_ubox表,这是一个弱值表,里面的数据是:ptr--->userdata。这个在这里是看不出来的,要到生成C++对象的时候才会知道。子类的tolua_ubox表是父类的tolua_ubox表或者是创建的一个新的表(没有父类的时候)
0 0
- tolua++的一些api的
- tolua++的一些想法
- tolua 一些可以用的函数
- tolua++导出c++接口时遇到的一些问题
- tolua 一些可以用的函数(测试过)
- tolua++导出C++类的一些问题和解决方法
- tolua++ api
- toLua:简洁的使用说明
- tolua++的使用
- tolua++的使用
- toLua++的使用
- tolua++的使用
- tolua++ 的pkg 脚本系统
- lua和tolua++的安装
- lua和tolua++的安装
- lua和tolua++的安装
- lua和tolua++的安装
- tolua 加载方式的学习
- 懒得笔记6 spring hibernate template
- 提交java性能的注意点
- Java学习--(九)异常处理
- android截图
- hdu5391Zball in Tina Town
- tolua++的一些api的
- Redis同步(主从复制)
- 关于flex匿名函数和swift闭包
- ACM对拍程序
- linux学习之路(6)
- C++对象模型详解
- Mybatis中#和$的区别
- @public 和 @protected
- 转oracle lag()和lead()函数