cocos2d lua绑定感悟---像cc.Sprite,cc.Director这些是如何识别的

cocos2d lua绑定感悟---像cc.Sprite,cc.Director这些是如何识别的,第1张

概述其实自从打开GameScene.lua文件以来,我一直都很想搞清楚的一个问题就是cc.Sprite这些是如何识别的。其实第一反应肯定就是:它肯定是一个全局变量,要不然怎么调用create方法呢。先不考究cocos的C++类方法是如何绑定到lua的,我就是想知道这个全局变量是什么时候注册的? 知道一点lua知识的都知道 lua里面的全局变量会保存到一个全局表_G中去,问题就转换为了 什么时候向_G中

其实自从打开GameScene.lua文件以来,我一直都很想搞清楚的一个问题就是cc.Sprite这些是如何识别的。其实第一反应肯定就是:它肯定是一个全局变量,要不然怎么调用create方法呢。先不考究cocos的C++类方法是如何绑定到lua的,我就是想知道这个全局变量是什么时候注册的?

知道一点lua知识的都知道 lua里面的全局变量会保存到一个全局表_G中去,问题就转换为了 什么时候向_G中注册的?在使用cc.Sprite的create之前,我好像没有没有在lua中定义cc.Sprite这样的变量,所以不可能是lua定义的这个全局变量,而是cocos在初始化lua引擎的时候对它进行注册的。

让我们来看看lua引擎初始化的时候都做了什么 *** 作。果然找到了_G的踪迹。

 luaL_register(_state,"_G",global_functions);

这是在向lua中注册全局函数。(关键是此时的栈顶是 全局表 啊!!!这点很重要)。

让我们继续看下去,我们会看到各种注册:

 register_all_cocos2dx(_state);    register_all_cocos2dx_extension(_state);    register_cocos2dx_extension_CCBProxy(_state);    tolua_opengl_open(_state);    register_all_cocos2dx_ui(_state);    register_all_cocos2dx_studio(_state);    register_all_cocos2dx_manual(_state);    register_all_cocos2dx_module_manual(_state);    register_all_cocos2dx_extension_manual(_state);    register_all_cocos2dx_coco_studio_manual(_state);    register_all_cocos2dx_ui_manual(_state);    register_all_cocos2dx_spine(_state);    register_all_cocos2dx_spine_manual(_state);    register_glnode_manual(_state);

每一个注册完成后,均会还原现场,即保持栈顶是_G表。让我们选一个来分析吧,就以register_all_cocos2dx 为例吧。
TolUA_API int register_all_cocos2dx(lua_State* tolua_S){	tolua_open(tolua_S);		tolua_module(tolua_S,"cc",0);	tolua_beginmodule(tolua_S,"cc");	lua_register_cocos2dx_Ref(tolua_S);	lua_register_cocos2dx_Console(tolua_S);		...省略很多代码...}

这里貌似看到一点苗头。cc和我们的cc.Sprite很近了。

基础函数介绍:

tolua_module:尝试注册以name为名的模块,每个模块都是在向父模块注册,但是cc没有父模块,所以它会认为_G是它该去注册的地方。

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);	/*	下面这段测试表明该模块是加到(全局表)中		if(lua_istable(L,-4)){		<span >	</span>lua_getfIEld(L,-4,"print");		<span >	</span>if(lua_isnil(L,-1)){		<span >		</span>char a='a';		<span >	</span>}else{		<span >		</span>char b ='b';  //come here啦啦啦!!!		<span >	</span>}		<span >	</span>lua_pop(L,1);	<span >	</span>}*/		//注册到当前模块表中去            lua_rawset(L,-4);       /* assing module into module */        }    }}
从上面的测试代码就可以发现就是向_G表注册。所以我们的猜测是完全正确的。为什么是_G表呢?之前已经提示过了(注册全局函数的时候,会把_G放在栈顶)。

现在全局表中有这样的一个键值对:_Gtable["cc"]=cc_table。

接下就看Sprite是如何注册进去的吧。在register_all_cocos2dx那堆注册的函数中,我们发现:

lua_register_cocos2dx_Sprite(tolua_S);

int lua_register_cocos2dx_Sprite(lua_State* tolua_S){    tolua_usertype(tolua_S,"cc.Sprite");    tolua_cclass(tolua_S,"Sprite","cc.Sprite","cc.Node",nullptr);    tolua_beginmodule(tolua_S,"Sprite");    tolua_function(tolua_S,"setSpriteFrame",lua_cocos2dx_Sprite_setSpriteFrame);	//...此处省略很多代码...}

基础函数介绍:

tolua_usertype:向注册表中注册该用户类型,创建该类型的表。(table和type在注册表中是双向映射)。

tolua_cclass:设置该类的元表啊,父类,tolua_super表注册,tolua_uBox表注册,。并且以"Sprite"为key加入到当前所在父模板表中。

然后是向表中注册一些函数。

我们知道当前父模板表是cc_table,当前模板表是:sprite_table。cc_table["Sprite"] = sprite_table。sprite_table["setSpriteFrame"] = lua_cocos2dx_Sprite_setSpriteFrame。

现在就可以通过全局表去访问 到Sprite了,并且可以访问到里面的方法。

所以我觉得cc.Sprite.setSpriteFrame(...)的执行流程是:向_G表中拿到cc对应的cc_table,再看在cc_table中是否有Sprite,如果有就在sprite_table中去寻找setSpriteFrame方法。

以上纯属个人看法。本人也是在学习中,欢迎和一起交流。

总结

以上是内存溢出为你收集整理的cocos2d lua绑定感悟---像cc.Sprite,cc.Director这些是如何识别的全部内容,希望文章能够帮你解决cocos2d lua绑定感悟---像cc.Sprite,cc.Director这些是如何识别的所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/web/1068569.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-26
下一篇 2022-05-26

发表评论

登录后才能评论

评论列表(0条)

保存