cocos2d+lua 귀속 관계 이해--2

12663 단어 cocos+lua
전면적으로cocos+Lua의 귀속 관계를 이해하려면cocos와lua의 상호작용에서 조작된 표(table)를 더욱 깊이 이해해야 한다. 이런 표는 대부분 등록표에 존재한다.
우선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)를 사용하여 계승 체계를 실현한다.
 

좋은 웹페이지 즐겨찾기