有很多关于如何在Lua中克隆Lua表的示例,但是我无法找到如何使用本机Lua C API执行此操作的任何示例。我试图用手做两次,但结果却是一个真正的(虽然有效)混乱。
有没有人有关于如何在C API中优雅地执行Lua表的浅表副本的任何提示或链接?
答案 0 :(得分:8)
您需要做的是定义Lua函数,然后将其分解为相关的API调用。
shallow_copy = function(tab)
local retval = {}
for k, v in pairs(tab) do
retval[k] = v
end
return retval
end
所以我们需要在堆栈和lua_State上获取表的索引。
void shallow_copy(lua_State* L, int index) {
/*Create a new table on the stack.*/
lua_newtable(L);
/*Now we need to iterate through the table.
Going to steal the Lua API's example of this.*/
lua_pushnil(L);
while(lua_next(L, index) != 0) {
/*Need to duplicate the key, as we need to set it
(one pop) and keep it for lua_next (the next pop). Stack looks like table, k, v.*/
lua_pushvalue(L, -2);
/*Now the stack looks like table, k, v, k.
But now the key is on top. Settable expects the value to be on top. So we
need to do a swaparooney.*/
lua_insert(L, -2);
/*Now we just set them. Stack looks like table,k,k,v, so the table is at -4*/
lua_settable(L, -4);
/*Now the key and value were set in the table, and we popped off, so we have
table, k on the stack- which is just what lua_next wants, as it wants to find
the next key on top. So we're good.*/
}
}
现在我们复制的表位于堆栈的顶部。
基督,Lua API很糟糕。
答案 1 :(得分:0)
HI以下代码段实现了Deepcopy,请尽情享受:
static int deepCopy(lua_State* L,int n,int CacheT)
{
int copyIndex = 0;
switch (lua_type(L, n))
{
case LUA_TNIL:
lua_pushnil(L);
copyIndex = lua_gettop(L);
break;
case LUA_TBOOLEAN:
lua_pushboolean(L, lua_toboolean(L, n));
copyIndex = lua_gettop(L);
break;
case LUA_TNUMBER:
lua_pushnumber(L, lua_tonumber(L, n));
copyIndex = lua_gettop(L);
break;
case LUA_TSTRING:
lua_pushlstring(L, lua_tostring(L, n), lua_rawlen(L, n));
copyIndex = lua_gettop(L);
break;
case LUA_TLIGHTUSERDATA:
case LUA_TUSERDATA:
lua_pushlightuserdata(L, (void*)lua_touserdata(L, n));
copyIndex = lua_gettop(L);
break;
case LUA_TFUNCTION:
lua_pushvalue(L, n);
copyIndex = lua_gettop(L);
break;
case LUA_TTHREAD:
lua_pushvalue(L, n);
copyIndex = lua_gettop(L);
break;
case LUA_TTABLE:
{
//push key
lua_pushvalue(L, n);
//try to get cached obj(should pop key from stack and push get value onto stack)
int32 type = lua_gettable(L, CacheT);
if (type == LUA_TTABLE)
{
//just return
copyIndex = lua_gettop(L);//push 1
}
else
{
//pop the pushed get table return value
lua_pop(L, 1);
{
lua_newtable(L);
copyIndex = lua_gettop(L);
//push key
lua_pushvalue(L, n);
//push value
lua_pushvalue(L, copyIndex);
//save created table into cacheT
lua_settable(L, CacheT);
/* table is in the stack at index 't' */
lua_pushnil(L); /* first key */
while (lua_next(L, n) != 0) {
/* uses 'key' (at index -2) and 'value' (at index -1) */
int keyIndex = lua_absindex(L, -2);//1
int valueIndex = lua_absindex(L, -1);//2
int copyedKey = deepCopy(L, keyIndex, CacheT);//3
int copyedValue = deepCopy(L, valueIndex, CacheT);//4
//push key
lua_pushvalue(L, copyedKey);
//push value
lua_pushvalue(L, copyedValue);
lua_settable(L, copyIndex);
/* removes 'value'; keeps 'key' for next iteration */
lua_pop(L, 3);
}
if (1 == lua_getmetatable(L, n))//try to get metatable of n(push onto stack if return 1)
{
int metaIndex = lua_gettop(L);
metaIndex = lua_absindex(L, -1);
//push 1
int copyedMeta = deepCopy(L, metaIndex, CacheT);//try to copy meta table push onto stack
lua_setmetatable(L, copyIndex);//set meta table and pop copyedMeta
lua_pop(L, 1);//pop lua_getmetatable pushed value
}
else
{
;//do nothing
}
}
}
break;
}
}
return copyIndex;
}
//following c++ equals lua logic like this:
/*
function _G.tclone(value)
local function __tclone(value,cached)
local copy
local cacheT = cached or {}
if type(value) == 'table' then
--if has been already cloned just return handle recursive
if nil ~= cacheT[value] then
copy = cacheT[value]
else
copy = {}
cacheT[value] = copy
for k,v in pairs(value) do
--clone key --clone value
copy[__tclone(k,cacheT)] = __tclone(v,cacheT)
end
--clone metatable
setmetatable(copy, __tclone(getmetatable(value), cacheT))
end
else
copy = value
end
return copy
end
return __tclone(value,nil)
end
---
*/
static int tClone(lua_State* L, int n)
{
int cacheT;
int copy;
lua_newtable(L);
cacheT = lua_gettop(L);
copy = deepCopy(L, n, cacheT);
lua_remove(L, cacheT);
return copy;
}