static void extendNode(lua_State* tolua_S)
{
lua_pushstring(tolua_S,"cc.Node");
lua_rawget(tolua_S,LUA_REGISTRYINDEX);
if (lua_istable(tolua_S,-1))
{
lua_pushstring(tolua_S,"registerScriptHandler");
lua_pushcfunction(tolua_S,tolua_cocos2d_Node_registerScriptHandler);
lua_rawset(tolua_S,-3);
lua_pushstring(tolua_S,"unregisterScriptHandler");
lua_pushcfunction(tolua_S,tolua_cocos2d_Node_unregisterScriptHandler);
lua_rawset(tolua_S, -3);
lua_pushstring(tolua_S,"scheduleUpdateWithPriorityLua");
lua_pushcfunction(tolua_S,tolua_Cocos2d_Node_scheduleUpdateWithPriorityLua);
lua_rawset(tolua_S, -3);
lua_pushstring(tolua_S,"unscheduleUpdate");
lua_pushcfunction(tolua_S,tolua_cocos2d_Node_unscheduleUpdate);
lua_rawset(tolua_S, -3);
lua_pushstring(tolua_S,"getPosition");
lua_pushcfunction(tolua_S,tolua_cocos2d_Node_getPosition);
lua_rawset(tolua_S, -3);
lua_pushstring(tolua_S, "setContentSize");
lua_pushcfunction(tolua_S, tolua_cocos2d_Node_setContentSize);
lua_rawset(tolua_S, -3);
lua_pushstring(tolua_S, "setAnchorPoint");
lua_pushcfunction(tolua_S, tolua_cocos2d_Node_setAnchorPoint);
lua_rawset(tolua_S, -3);
lua_pushstring(tolua_S, "enumerateChildren");
lua_pushcfunction(tolua_S, lua_cocos2dx_Node_enumerateChildren);
lua_rawset(tolua_S, -3);
}
lua_pop(tolua_S, 1);
}
int lua_register_cocos2dx_Node(lua_State* tolua_S)
{
tolua_usertype(tolua_S,"cc.Node");
tolua_cclass(tolua_S,"Node","cc.Node","cc.Ref",nullptr);
tolua_beginmodule(tolua_S,"Node");
tolua_function(tolua_S,"addChild",lua_cocos2dx_Node_addChild);
tolua_function(tolua_S,"removeComponent",lua_cocos2dx_Node_removeComponent);
tolua_function(tolua_S,"setPhysicsBody",lua_cocos2dx_Node_setPhysicsBody);
tolua_function(tolua_S,"getDescription",lua_cocos2dx_Node_getDescription);
tolua_function(tolua_S,"setRotationSkewY",lua_cocos2dx_Node_setRotationSkewY);
tolua_function(tolua_S,"setOpacityModifyRGB",lua_cocos2dx_Node_setOpacityModifyRGB);
tolua_function(tolua_S,"setCascadeOpacityEnabled",lua_cocos2dx_Node_setCascadeOpacityEnabled);
tolua_function(tolua_S,"getChildren",lua_cocos2dx_Node_getChildren);
//....省略
tolua_function(tolua_S,"stopAction",lua_cocos2dx_Node_stopAction);
tolua_function(tolua_S,"getActionManager",lua_cocos2dx_Node_getActionManager);
tolua_function(tolua_S,"create", lua_cocos2dx_Node_create);
tolua_endmodule(tolua_S);
std::string typeName = typeid(cocos2d::Node).name();
g_luaType[typeName] = "cc.Node";
g_typeCast["Node"] = "cc.Node";
return 1;
}
举例:cc.Layer派生与cc.Node,cc.Node派生与cc.Ref
int lua_register_cocos2dx_Layer(lua_State* tolua_S)
{
tolua_usertype(tolua_S,"cc.Layer");
tolua_cclass(tolua_S,"Layer","cc.Layer","cc.Node",nullptr);
tolua_beginmodule(tolua_S,"Layer");
tolua_function(tolua_S,"create", lua_cocos2dx_Layer_create);
tolua_endmodule(tolua_S);
std::string typeName = typeid(cocos2d::Layer).name();
g_luaType[typeName] = "cc.Layer";
g_typeCast["Layer"] = "cc.Layer";
return 1;
}
int lua_register_cocos2dx_Node(lua_State* tolua_S)
{
tolua_usertype(tolua_S,"cc.Node");
tolua_cclass(tolua_S,"Node","cc.Node","cc.Ref",nullptr);
tolua_beginmodule(tolua_S,"Node");
tolua_function(tolua_S,"addChild",lua_cocos2dx_Node_addChild);
tolua_function(tolua_S,"removeComponent",lua_cocos2dx_Node_removeComponent);
tolua_function(tolua_S,"setPhysicsBody",lua_cocos2dx_Node_setPhysicsBody);
tolua_function(tolua_S,"getDescription",lua_cocos2dx_Node_getDescription);
tolua_function(tolua_S,"setRotationSkewY",lua_cocos2dx_Node_setRotationSkewY);
tolua_function(tolua_S,"setOpacityModifyRGB",lua_cocos2dx_Node_setOpacityModifyRGB);
tolua_function(tolua_S,"setCascadeOpacityEnabled",lua_cocos2dx_Node_setCascadeOpacityEnabled);
tolua_function(tolua_S,"getChildren",lua_cocos2dx_Node_getChildren);
//....省略
tolua_function(tolua_S,"stopAction",lua_cocos2dx_Node_stopAction);
tolua_function(tolua_S,"getActionManager",lua_cocos2dx_Node_getActionManager);
tolua_function(tolua_S,"create", lua_cocos2dx_Node_create);
tolua_endmodule(tolua_S);
std::string typeName = typeid(cocos2d::Node).name();
g_luaType[typeName] = "cc.Node";
g_typeCast["Node"] = "cc.Node";
return 1;
}
上面的代码主要做下列操作:
cc.Layer的元表被设置成cc.Node
cc.Node的元表被设置成cc.Ref
cc.Ref的元表被设置成tolua_commonclass
如果你调用cc.Layer函数,例如对象layer:abc()(layer是一个cc.Layer对象)。layer的元表被成cc.Layer
lua先在cc.Layer中查找abc函数,然后是cc.Node,最后是cc.Ref。
local A={
__index = A,
abc=function()
print('abc')
end
}
A.__index = A
local B={
bbb=function()
print('bbb')
end
}
B.__index = B
local C=
{
ccc=function()
print('ccc')
end
}
C.__index = C
local obj = {}
setmetatable(B,A)
setmetatable(C,B)
setmetatable(obj,C)
obj:ccc()
obj:bbb()
obj:abc()
最终tolua++要解决下列问题:
1.已知元表mt取的元表名称_R[mt]
2.已知名称取的原表luaL_getmetatable(L,name)
3.已知元表取继承关系
_R["tolua_super"][mt] = {
super1 = true,
super2 = true,
...,
}
4.已知一个lua对象,取C++对象.
如果该lua对象是一个userdata,返回userdata,如果是一个表返回表的c_instance
可以使用tolua_isusertype来检查对象是不是给定的类型,例如tolua_isusertype(tolua_S,1,"cc.Ref",0,&tolua_err)检查堆栈1,是不是一个cc.Ref对象.
而cobj = (cocos2d::Ref*)tolua_tousertype(tolua_S,1,0);将取出该对象。
5.tolua.getpeer(target) 取的target的环境.如果等于_R,就返回nil
tolua.setpeer(target,t)设置target的环境,target必须是一个userdata
例如:
function HomeWork.extend(target)
local t = tolua.getpeer(target)
if not t then
t = {}
tolua.setpeer(target, t)
end
setmetatable(t, HomeWork)
return target
end
local layer = HomeWork.extend(cc.Layer:create())
对于一个函数的调用顺序是这样的,先t表(layer的环境表)中的,然后到t的元表HomeWork中,其实才是cc.Layer
6.lua对象的绑定
例如:绑定一个场景对象为一个lua对象
object_to_luaval
template
void object_to_luaval(lua_State* L,const char* type, T* ret)
{
if(nullptr != ret)
{
cocos2d::Ref* dynObject = dynamic_cast(ret);
if (nullptr != dynObject)
{
int ID = (int)(dynObject->_ID) ;
int* luaID = &(dynObject->_luaID);
toluafix_pushusertype_ccobject(L,ID, luaID, (void*)ret,type);
}
else
{
tolua_pushusertype(L,(void*)ret,getLuaTypeName(ret, type));
}
}
else
{
lua_pushnil(L);
}
}
7.对象的释放
对象都从Ref派生,都使用引用计数管理。
~Ref的实现如下:
Ref::~Ref()
{
#if CC_ENABLE_SCRIPT_BINDING
// if the object is referenced by Lua engine, remove it
if (_luaID)
{
ScriptEngineManager::getInstance()->getScriptEngine()->removeScriptObjectByObject(this);
}
else
{
ScriptEngineProtocol* pEngine = ScriptEngineManager::getInstance()->getScriptEngine();
if (pEngine != nullptr && pEngine->getScriptType() == kScriptTypeJavascript)
{
pEngine->removeScriptObjectByObject(this);
}
}
#endif
#if CC_USE_MEM_LEAK_DETECTION
if (_referenceCount != 0)
untrackRef(this);
#endif
}
最后调用toluafix_remove_ccobject_by_refid(_state, pObj->_luaID);和void ScriptHandlerMgr::removeObjectAllHandlers(void* object)
8.tolua_ubox
9.对象创建
用法:创建类元表
_R[mt] = class_name
int tolua_isusertype (lua_State* L, int lo, const char* type, int def, tolua_Error* err)
int lua_isusertype (lua_State* L, int lo, const char* type)
lo必须是一个userdata或者table.(mt是lo的原表),并且lo必须有元表
如果_R[mt] == type ,表示他是一个type 类型数据.
或者_R["tolua_super"][mt]是一个表ST,并且ST[type]如果不为nil或者false,表示lo是type的子类的实例.
static int lua_isusertable (lua_State* L, int lo, const char* type)
如果_R[lo]==type,返回true
int tolua_fast_isa(lua_State *L, int mt_indexa, int mt_indexb, int super_index)
void tolua_pushusertype_internal (lua_State* L, void* value, const char* type, int addToRoot)
如果存在名称为type的原表mt.
C = mt["tolua_ubox"] or _R["tolua_ubox"]
C[value]