这个系列我们主要学习Cocos2d-x Lua,总结Lua开发过程中所涉及的知识点,以及在开发过程中如何使用Cocos Code IDE。这一篇讲解Lua Binding实现C++里访问Lua的自定义对象。
LUABinding比JSBinding要简单,无论是使用脚本自动绑定还是手动写绑定代码,都能很轻松实现在Lua访问C++的类和对象。但如果想在C++里访问Lua里的自定义类和对象,则需要再自己修改一下C++的代码了。
应用场景
1、假设在Lua里有一个类MyLayer,继承了CCLayer,并添加了a、b、c、d这4个属性。
2、在Lua里,创建一个MyLayer的实例对象,并添加到当前的Scene中,然后通过Scene.getChildByTag方法拿出这个MyLayer的实例对象时,会发现自定义属性a、b、c、d都消失了,原因在于调用了toluafix_pushusertype_ccobject(tolua_S,nID,pLuaID,(void*)tolua_ret,"CCNode");返回的是一个CCNode,下面是LuaCocos2d.cpp里的代码:
static int tolua_Cocos2d_CCNode_getChildByTag00(lua_State* tolua_S) { #ifndef TOLUA_RELEASE tolua_Error tolua_err; if ( !tolua_isusertype(tolua_S,1,"CCNode",0,&tolua_err) || !tolua_isnumber(tolua_S,2,0,&tolua_err) || !tolua_isnoobj(tolua_S,3,&tolua_err) ) goto tolua_lerror; else #endif { CCNode* self = (CCNode*) tolua_tousertype(tolua_S,1,0); int tag = ((int) tolua_tonumber(tolua_S,2,0)); #ifndef TOLUA_RELEASE if (!self) tolua_error(tolua_S,"invalid 'self' in function 'getChildByTag'", NULL); #endif { CCNode* tolua_ret = (CCNode*) self->getChildByTag(tag); int nID = (tolua_ret) ? (int)tolua_ret->m_uID : -1; int* pLuaID = (tolua_ret) ? &tolua_ret->m_nLuaID : NULL; toluafix_pushusertype_ccobject(tolua_S, nID, pLuaID, (void*)tolua_ret,"CCNode"); } } return 1; #ifndef TOLUA_RELEASE tolua_lerror: tolua_error(tolua_S,"#ferror in function 'getChildByTag'.",&tolua_err); return 0; #endif }
解决的方法很简单
a)首先先调用tolua_usertype(tolua_S,"MyLayer");,注册自定义类,这句代码可以加在任何可以调用lua_State*这个指针的地方,但必须在初始化时只调用一次即可。
b)将以下代码写在LuaCocos2d.cpp里,自己看着位置来放:
//扩展了getChildByTag,可以返回lua的对象,by lizc /* method: getChildByTag of class CCNode */ #ifndef TOLUA_DISABLE_tolua_Cocos2d_CCNode_getChildByTag01 static int tolua_Cocos2d_CCNode_getChildByTag01(lua_State* tolua_S) { #ifndef TOLUA_RELEASE tolua_Error tolua_err; if ( !tolua_isusertype(tolua_S,1,"CCNode",0,&tolua_err) || !tolua_isnumber(tolua_S,2,0,&tolua_err) || (!tolua_isvaluenil(tolua_S,3,&tolua_err) && !tolua_isstring(tolua_S,3,0,&tolua_err)) || !tolua_isnoobj(tolua_S,4,&tolua_err) ) goto tolua_lerror; else #endif { CCNode* self = (CCNode*) tolua_tousertype(tolua_S,1,0); int tag = ((int) tolua_tonumber(tolua_S,2,0)); const char* userTypeName = ((const char*) tolua_tostring(tolua_S,3,0)); #ifndef TOLUA_RELEASE if (!self) tolua_error(tolua_S,"invalid 'self' in function 'getChildByTag'", NULL); #endif { CCNode* tolua_ret = (CCNode*) self->getChildByTag(tag); int nID = (tolua_ret) ? (int)tolua_ret->m_uID : -1; int* pLuaID = (tolua_ret) ? &tolua_ret->m_nLuaID : NULL; toluafix_pushusertype_ccobject(tolua_S, nID, pLuaID, (void*)tolua_ret, userTypeName); } } return 1; #ifndef TOLUA_RELEASE tolua_lerror: return tolua_Cocos2d_CCNode_getChildByTag00(tolua_S); #endif } #endif //#ifndef TOLUA_DISABLE
c)再添加
tolua_function(tolua_S,"getChildByTag",tolua_Cocos2d_CCNode_getChildByTag01);
到
tolua_function(tolua_S,"getChildByTag",tolua_Cocos2d_CCNode_getChildByTag00);
下面,方便管理。
使用方法
--MyLayer必须继承自C++的某个类,这里就是继承CCLayer local myLayer = MyLayer:create() myLayer.a = 1 myLayer.b = 2 local scene = CCScene:create() scene:addChild(myLayer, 0, 0) myLayer = scene:getChildByTag(0, “MyLayer”) myLayer = tolua.cast(myLayer, “MyLayer”) cclog(“myLayer.a” .. myLayer.a) cclog(“myLayer.b” .. myLayer.b)