luaL_ref
및 luaL_unref
기능은 lauxlib.c
에 정의되어 있습니다. 그들은 작동중인 테이블에 저장하는 무료 참조 목록을 추적하여 작동합니다. 이 함수는 비교적 짧기 때문에 여기서 그 함수를 포함 할 것입니다. 그들이 (그들은에서 작동하는 테이블 이외의) 추가 스토리지를 필요로하지 않기 때문에
LUALIB_API int luaL_ref (lua_State *L, int t) {
int ref;
t = abs_index(L, t);
if (lua_isnil(L, -1)) {
lua_pop(L, 1); /* remove from stack */
return LUA_REFNIL; /* 'nil' has a unique fixed reference */
}
lua_rawgeti(L, t, FREELIST_REF); /* get first free element */
ref = (int)lua_tointeger(L, -1); /* ref = t[FREELIST_REF] */
lua_pop(L, 1); /* remove it from stack */
if (ref != 0) { /* any free element? */
lua_rawgeti(L, t, ref); /* remove it from list */
lua_rawseti(L, t, FREELIST_REF); /* (t[FREELIST_REF] = t[ref]) */
}
else { /* no free elements */
ref = (int)lua_objlen(L, t);
ref++; /* create new reference */
}
lua_rawseti(L, t, ref);
return ref;
}
LUALIB_API void luaL_unref (lua_State *L, int t, int ref) {
if (ref >= 0) {
t = abs_index(L, t);
lua_rawgeti(L, t, FREELIST_REF);
lua_rawseti(L, t, ref); /* t[ref] = t[FREELIST_REF] */
lua_pushinteger(L, ref);
lua_rawseti(L, t, FREELIST_REF); /* t[FREELIST_REF] = ref */
}
}
이 기능은 정말 영리하다. 그러나 참조 된 값을 반복 할 필요가있을 때처럼 참조 된 값과 동일한 테이블에 자유 참조 목록을 저장하는 것이 바람직하지 않은 경우가 있습니다.
이 문제를 해결하기 위해 luaX_ref
및 luaX_unref
으로 작성했습니다. luaL_ref
및 luaL_unref
과 거의 동일하게 작동하지만, 무료 참조 목록을 별도의 테이블에 저장합니다 (l
목록). (내 프로젝트를 위해, 나는 별도의 소스 파일에 다음을 넣어했고 필요에 포함 한 내가 lauxlib.c
을 수정하지 않는 것이 좋습니다..)
static int abs_index(lua_State * L, int i){
return i > 0 || i <= LUA_REGISTRYINDEX ? i : lua_gettop(L) + i + 1;
}
LUALIB_API int luaX_ref(lua_State *L, int t, int l){
int ref;
t = abs_index(L, t);
l = abs_index(L, l);
if(lua_isnil(L, -1)){
lua_pop(L, 1); /* remove from stack */
return LUA_REFNIL; /* 'nil' has a unique fixed reference */
}
lua_rawgeti(L, l, FREELIST_REF); /* get first free element */
ref = (int) lua_tointeger(L, -1); /* ref = l[FREELIST_REF] */
lua_pop(L, 1); /* remove it from stack */
if(ref != 0){ /* any free element? */
lua_rawgeti(L, l, ref); /* remove it from list */
lua_rawseti(L, l, FREELIST_REF); /* (l[FREELIST_REF] = l[ref]) */
}else{ /* no free elements */
ref = (int)lua_objlen(L, l);
ref++; /* create new reference */
}
lua_pushboolean(L, 1);
lua_rawseti(L, l, ref); /* l[ref] = true */
lua_rawseti(L, t, ref); /* t[ref] = value */
return ref;
}
LUALIB_API void luaX_unref(lua_State *L, int t, int l, int ref){
if(ref >= 0){
t = abs_index(L, t);
l = abs_index(L, l);
lua_rawgeti(L, l, FREELIST_REF);
lua_rawseti(L, l, ref); /* l[ref] = l[FREELIST_REF] */
lua_pushinteger(L, ref);
lua_rawseti(L, l, FREELIST_REF); /* l[FREELIST_REF] = ref */
lua_pushnil(L);
lua_rawseti(L, t, ref); /* t[ref] = nil */
}
}
지금 사용을 참조하십시오
lua_newtable(L); /* 1 */
lua_newtable(L); /* 2 */
lua_pushboolean(L, 0);
int ref1 = luaX_ref(L, 1, 2);
lua_pushinteger(L, 7);
int ref2 = luaX_ref(L, 1, 2);
lua_pushstring(L, "test");
int ref3 = luaX_ref(L, 1, 2);
tableDump(L, 1);
tableDump(L, 2);
luaX_unref(L, 1, 2, ref1);
tableDump(L, 1);
tableDump(L, 2);
luaX_unref(L, 1, 2, ref3);
tableDump(L, 1);
tableDump(L, 2);
luaX_unref(L, 1, 2, ref2);
tableDump(L, 1);
tableDump(L, 2);
printf("done.\n");
출력 :
1: false, 2: 7, 3: `test',
1: true, 2: true, 3: true,
2: 7, 3: `test',
3: true, 2: true, 0: 1,
2: 7,
3: 1, 2: true, 0: 3,
3: 1, 2: 3, 0: 2,
done.
저는 Lua 5.1을 사용하고 있습니다. – tprk77
API 악용을 중지하십시오. 'luaL_ref'와'luaL_unref'의 목적은 "테이블을 채우는"것이 아닙니다. 참조로 값을 저장하고 나중에 다시 가져올 수있는 간단한 참조 시스템을 만드는 것입니다. 당신은 테이블 위에서 반복해서는 안됩니다. 반환 된 참조를 사용하여 테이블 항목에 액세스해야합니다. –