cocos2d+lua 귀속 관계 이해--2
12663 단어 cocos+lua
우선cocos의 대상이 루아의userdata에 대응하고 귀속된 원표를 보십시오
cc.Sprite 예
["cc.Sprite"] = {--table: 0x0032c690
["new"] = "function: 0x00b9b168",
["__lt"] = "function: 0x0032cbf0",
["__sub"] = "function: 0x0032cc58",
["__newindex"] = "function: 0x0032c710",
["__eq"] = "function: 0x0032cc30",
["__le"] = "function: 0x0032cc10",
["createWithSpriteFrame"] = "function: 0x00b9be50",
["createWithSpriteFrameName"] = "function: 0x00b9be00",
["tolua_ubox"] = "table: 0x002c86f0" , -- loop table,
["createWithTexture"] = "function: 0x00b9b5c0"
["__div"] = "function: 0x0032c6b8",
["__index"] = "function: 0x0032c6f0",
["__gc"] = "function: 0x002c1a90",
["__call"] = "function: 0x0032cc98",
["__mul"] = "function: 0x0032cc78",
["__add"] = "function: 0x0032c730",
[".metatable"] = table: 0x002ca9c8,
......
},
["cc.Node"] = {--table: 0x002ca9c8
["visit"] = "function: 0x002cc550",
["setVisible"] = "function: 0x002cddb8",
["__index"] = "function: 0x002c7ec8",
["getPosition"] = "function: 0x010b3bf8",
["setPosition"] = "function: 0x002cccb8",
["setRotation"] = "function: 0x002cc030",
["create"] = "function: 0x002cd220",
["init"] = "function: 0x002cbfa8",
["__newindex"] = "function: 0x002c7ee8",
["__call"] = "function: 0x002cb588",
["__eq"] = "function: 0x002cb650",
["__add"] = "function: 0x002c7f08",
["__sub"] = "function: 0x002ca9f0",
["__gc"] = "function: 0x002c1a90",
["__lt"] = "function: 0x002c7f48",
["__mul"] = "function: 0x002caa10",
["__le"] = "function: 0x002c7f68",
["tolua_ubox"] = "table: 0x002c86f0" , -- loop table,
["__div"] = "function: 0x002c7f28",
["new"] = "function: 0x002c9e50",
["addChild"] = "function: 0x002c9e90",
[".metatable"] = table: 0x002c7070,
......
},
["cc.Ref"] = {--table: 0x002c7070
["__le"] = "function: 0x002c8458",
["getReferenceCount"] = "function: 0x002c8938",
["retain"] = "function: 0x002c88f0",
["tolua_ubox"] = "table: 0x002c86f0" , -- loop table,
["release"] = "function: 0x002c88b0",
["__gc"] = "function: 0x002c1a90",
["__lt"] = "function: 0x002c8438",
["__newindex"] = "function: 0x002c8220",
["__call"] = "function: 0x002c84a0",
["__add"] = "function: 0x002c8240",
["__eq"] = "function: 0x002c8478",
["__sub"] = "function: 0x002c8260",
["__div"] = "function: 0x002c81e8",
["__mul"] = "function: 0x002c8280",
["__index"] = "function: 0x002c7098",
[".metatable"] = table: 0x002c1ae8
},
["tolua_commonclass"] = {--table: 0x002c1ae8
["__le"] = "function: 0x002c1d58",
["__gc"] = "function: 0x002c1a90",
["__lt"] = "function: 0x002c1d38",
["__newindex"] = "function: 0x002c1b68",
["__call"] = "function: 0x002c1d98",
["__add"] = "function: 0x002c1b88",
["__eq"] = "function: 0x002c1d78",
["__sub"] = "function: 0x002c1c10",
["__div"] = "function: 0x002c1d18",
["__mul"] = "function: 0x002c1c30",
["__index"] = "function: 0x002c1b48",
},
코코스가 루아에서 원표(metatable)로 계승 체계를 실현한 것을 알 수 있다.Sprite 메타테이블은 cc입니다.Node,cc.Node의 원표는 cc입니다.Ref,cc.Ref의 원표는 tolua_commonclass,cocos는 각 바인딩된 메타테이블에 "__index", "_newindex", "_add", "_sub", "_mul", "_div", "_lt", "_le", "_eq", "_call", "_gc"방법을 추가합니다.
"__index"방법은 검색 기능을 제공합니다. 가장 많이 사용하는 방법입니다. userdata에 모든 귀속 방법을 찾을 수 있는 기능을 제공합니다. c++ 바늘을 사용하듯이 루아의userdata를 사용할 수 있습니다.
static int class_index_event (lua_State* L)
{
int t = lua_type(L,1);
//userdata
if (t == LUA_TUSERDATA)
{
// ,
lua_getfenv(L,1);
if (!lua_rawequal(L, -1, TOLUA_NOPEER)) {
lua_pushvalue(L, 2); /* key */
lua_gettable(L, -2); /* on lua 5.1, we trade the "tolua_peers" lookup for a gettable call */
if (!lua_isnil(L, -1))
return 1;
}
lua_settop(L,2); /* stack: obj key */
/* Try metatables */
lua_pushvalue(L,1); /* stack: obj key obj */
// userdata
while (lua_getmetatable(L,-1))
{ /* stack: obj key obj mt */
lua_remove(L,-2); /* stack: obj key mt */
// key number , self[1]
if (lua_isnumber(L,2)) /* check if key is a numeric value */
{
// .geti ,
lua_pushstring(L,".geti");
lua_rawget(L,-2); /* stack: obj key mt func */
if (lua_isfunction(L,-1))
{
lua_pushvalue(L,1);
lua_pushvalue(L,2);
lua_call(L,2,1);
return 1;
}
}
else
{
// ,
lua_pushvalue(L,2); /* stack: obj key mt key */
lua_rawget(L,-2); /* stack: obj key mt value */
if (!lua_isnil(L,-1))
return 1;
else
lua_pop(L,1);
/* .get */
lua_pushstring(L,".get");
lua_rawget(L,-2); /* stack: obj key mt tget */
if (lua_istable(L,-1))
{
lua_pushvalue(L,2);
lua_rawget(L,-2); /* stack: obj key mt value */
if (lua_iscfunction(L,-1))
{
lua_pushvalue(L,1);
lua_pushvalue(L,2);
lua_call(L,2,1);
return 1;
}
else if (lua_istable(L,-1))
{
/* deal with array: create table to be returned and cache it in ubox */
void* u = *((void**)lua_touserdata(L,1));
lua_newtable(L); /* stack: obj key mt value table */
lua_pushstring(L,".self");
lua_pushlightuserdata(L,u);
lua_rawset(L,-3); /* store usertype in ".self" */
lua_insert(L,-2); /* stack: obj key mt table value */
lua_setmetatable(L,-2); /* set stored value as metatable */
lua_pushvalue(L,-1); /* stack: obj key met table table */
lua_pushvalue(L,2); /* stack: obj key mt table table key */
lua_insert(L,-2); /* stack: obj key mt table key table */
storeatubox(L,1); /* stack: obj key mt table */
return 1;
}
}
}
lua_settop(L,3);
}
lua_pushnil(L);
return 1;
}
else if (t== LUA_TTABLE)
{
lua_pushvalue(L,1);
class_table_get_index(L);
return 1;
}
lua_pushnil(L);
return 1;
}
__index 방법 대응 c 함수 class_index_이벤트, 이 함수는userdata와table 두 가지 상황으로 나누어 처리하고 호출자의 유형에 따라 판단하기 때문에 반드시 사용해야 합니다: 호출해야 합니다.호출자가 표(table)인 경우 지난 블로그에 소개가 있습니다. 호출이 모두userdata인 상황을 주로 보십시오.프로세스는:userdata를 창고 꼭대기에 눌러서userdata의 메타테이블 (metatable) 을 가져옵니다. 만약 키가number이고 존재한다면.geti 함수는 이 함수를 호출합니다. 다른 형식은 원표에서 찾을 수 없습니다.get 테이블에서 검색을 시도합니다.
____newindex 대응 c 함수 class_newindex_event
static int class_newindex_event (lua_State* L)
{
int t = lua_type(L,1);
if (t == LUA_TUSERDATA)
{
/* Try accessing a C/C++ variable to be set */
lua_getmetatable(L,1);
while (lua_istable(L,-1)) /* stack: t k v mt */
{
// self[i] , .seti ,
if (lua_isnumber(L,2)) /* check if key is a numeric value */
{
/* try operator[] */
lua_pushstring(L,".seti");
lua_rawget(L,-2); /* stack: obj key mt func */
if (lua_isfunction(L,-1))
{
lua_pushvalue(L,1);
lua_pushvalue(L,2);
lua_pushvalue(L,3);
lua_call(L,3,0);
return 0;
}
}
else
{
// .set ,
lua_pushstring(L,".set");
lua_rawget(L,-2); /* stack: t k v mt tset */
if (lua_istable(L,-1))
{
lua_pushvalue(L,2);
lua_rawget(L,-2); /* stack: t k v mt tset func */
if (lua_iscfunction(L,-1))
{
lua_pushvalue(L,1);
lua_pushvalue(L,3);
lua_call(L,2,0);
return 0;
}
lua_pop(L,1); /* stack: t k v mt tset */
}
lua_pop(L,1); /* stack: t k v mt */
if (!lua_getmetatable(L,-1)) /* stack: t k v mt mt */
lua_pushnil(L);
lua_remove(L,-2); /* stack: t k v mt */
}
}
lua_settop(L,3); /* stack: t k v */
/* */
storeatubox(L,1);
}
else if (t== LUA_TTABLE)
{
lua_getmetatable(L,1); /* stack: t k v mt */
lua_pushstring(L,".set");
lua_rawget(L,-2); /* stack: t k v mt tset */
if (lua_istable(L,-1)) {
lua_pushvalue(L,2); /* stack: t k v mt tset k */
lua_rawget(L,-2);
if (lua_iscfunction(L,-1)) { /* ... func */
lua_pushvalue(L,1); /* ... func t */
lua_pushvalue(L,3); /* ... func t v */
lua_call(L,2,0);
return 0;
}
}
lua_settop(L,3);
class_backup_before_newindex(L);
lua_settop(L,3);
lua_getmetatable(L,1); /* stack: t k v mt */
lua_replace(L, 1); /* stack: mt k v */
lua_rawset(L,1);
}
return 0;
}
호출자가userdata일 때, 키가number 형식이고 존재하면 메타테이블 (metatable) 을 압축합니다.seti 함수는 이 함수를 호출하고, 다른 유형은 존재한다.set 테이블 그리고.set표의 키 필드는 함수로서 이 함수를 호출합니다. 다른 경우storeatubox 함수를 호출합니다. 이 함수의 역할은 키와value를 새 표에 저장하여 찾을 때 사용하도록 하는 것입니다.
"__add", "__sub", "_mul", "__div", "_lt", "__eq", "userdata의 가감 곱셈, 비교 조작을 실현할 수 있으며, 테이블에서".add",".sub",".mul",".div",".lt",".le",".eq"방법을 찾을 수 있습니다. 이 방법은 기본적으로 제공되지 않습니다.
"__call"필드에서 ".call"방법을 찾고 호출합니다. 호출자는 table이어야 하며userdata가 될 수 없습니다.
"__gc"귀속 c 함수 class_gc_이벤트, 이 방법을 통해 c++ 대상 메모리에 대한 방출을 실현합니다.우리가 수동으로 대상의 생명주기 관리를 해야 하는 대상은 만들 때 tolua_를 호출해야 한다register_gc는 "tolua_gc"표에 대상 주소를 등록합니다. 이 대상은 수동으로 방출되어야 합니다. 루아층에서 쓰레기 회수를 할 때 루아는 자동으로class_를 호출합니다.gc_event,class_gc_이벤트는 이 대상의 메모리 공간을 검사하고 방출합니다.주의해야 할 것은 기본 방출 호출은free 함수입니다. new가 만든 대상은 사용자 정의 ".collector"함수로 방출해야 합니다.
요약:
cocos는 루아의 원표(metatable)를 사용하여 계승 체계를 실현한다.