如何遍历使用luaL_ref和luaL_unref修改的表?
2012-10-7 22:0:35
收藏:0
阅读:126
评论:1
我使用Lua的C API来扩展Lua。在我的模块中,我想要使用luaL_ref填充一个表,并使用luaL_unref删除字段。我还希望能够遍历此表,希望使用lua_next。
因为luaL_unref的原因,遍历表是一个问题。在Lua中,“删除”表字段通常是通过赋值为nil来完成的(因为未初始化的表字段会计算为nil)。next函数足够智能以跳过nil。我本来以为luaL_unref会将未引用的表字段分配给nil,但它似乎分配了一个整数。这个整数的值似乎没有被记录在案。
请考虑以下代码:
/* tableDump 打印表: */
/* key: value, key: value, ... */
lua_newtable(L);
lua_pushboolean(L, 0);
int ref1 = luaL_ref(L, -2);
lua_pushinteger(L, 7);
int ref2 = luaL_ref(L, -2);
lua_pushstring(L, "test");
int ref3 = luaL_ref(L, -2);
tableDump(L, -1);
luaL_unref(L, -1, ref1);
tableDump(L, -1);
luaL_unref(L, -1, ref3);
tableDump(L, -1);
luaL_unref(L, -1, ref2);
tableDump(L, -1);
printf("done.\n");
输出:
1: false, 2: 7, 3: `test',
3: `test', 2: 7, 0: 1,
3: 1, 2: 7, 0: 3,
3: 1, 2: 3, 0: 2,
done.
这是怎么回事?我该如何解决这个问题?有没有一些技巧可以迭代引用并忽略未引用的引用?我必须停止使用luaL_ref和luaL_unref吗?
编辑
首先,感谢您的回复!
也许我问错了问题。
让我更具体一些。我有一个客户端userdata,需要管理许多订阅userdata。通过客户端的subscribe方法创建订阅。通过客户端的unsubscribe方法删除订阅。订阅userdatas基本上是一种实现细节,因此它们不会在客户端API中暴露。相反,客户端API使用订阅引用,因此使用luaL_ref填充订阅表。
ref = client:sub(channel, func)
cleint:unsub(ref)
这就是问题所在。我希望客户端在__gc上自动取消所有剩余的订阅(否则用户将获得段错误)。因此,似乎我需要遍历订阅。我真的在滥用API吗?还有其他更好的方法吗?
点赞
评论区的留言会收到邮件通知哦~
推荐文章
- 如何将两个不同的lua文件合成一个 东西有点长 大佬请耐心看完 我是小白研究几天了都没搞定
- 如何在roblox studio中1:1导入真实世界的地形?
- 求解,lua_resume的第二次调用继续执行协程问题。
- 【上海普陀区】内向猫网络招募【Skynet游戏框架Lua后端程序员】
- SF爱好求教:如何用lua实现游戏内调用数据库函数实现账号密码注册?
- Lua实现网站后台开发
- LUA错误显式返回,社区常见的规约是怎么样的
- lua5.3下载库失败
- 请问如何实现文本框内容和某个网页搜索框内容连接,并把网页输出来的结果反馈到另外一个文本框上
- lua lanes多线程使用
- 一个kv数据库
- openresty 有没有比较轻量的 docker 镜像
- 想问一下,有大佬用过luacurl吗
- 在Lua执行过程中使用Load函数出现问题
- 为什么 neovim 里没有显示一些特殊字符?
- Lua比较两个表的值(不考虑键的顺序)
- 有个lua简单的项目,外包,有意者加微信 liuheng600456详谈,最好在成都
- 如何在 Visual Studio 2022 中运行 Lua 代码?
- addEventListener 返回 nil Lua
- Lua中获取用户配置主目录的跨平台方法
为了“确保返回的关键字的唯一性”,
luaL_ref必须维护一个已使用并随后被luaL_unref删除的键的列表。看起来,这个列表从t[0]开始,一直延续到索引的链路指向一个nil。这个列表保存在与活动参考相同的表中。如果你想像Nicol观察到的那样继续“滥用API”,并且依赖于实现定义的行为,你可以沿着这个链接列表查看一个键是否为已删除的参考,并在迭代表时进行跳过。或者为了避免依赖于实现定义的行为并且具有更高的性能,你可以保留一个单独的已删除参考表,在迭代表时跳过它们,虽然你需要忽略
t[0]处的列表头。如果你真的需要迭代引用,你可能最好使用完全不同的机制。你可以简单地将所有的参考/值对放在一个单独的表中,并在删除参考时将单独表中的值设置为
nil。然后你可以简单地迭代单独的表。