我在一个资源非常有限的系统中使用 Lua 与 C 结合使用。
我正在使用的库创建了一些对其创建的对象的引用(作为指针),这对于以后访问这些对象很有用。为了向 Lua 公开该库的功能,当创建此类对象时,该引用将返回给 Lua 脚本。
用户可以根据自己的喜好存储此引用,因为这使得以后的调用非常方便。
示例案例:
ref = MyLib.createObject("some", arguments)
local ref = MyLib.createObject("some", arguments)
table_of_refs[45] = MyLib.createObject("some", arguments)
-- etc...
不幸的是,这些引用可能会在 Lua 脚本范围之外(从 C 内部)被破坏。因此,这些引用可能会变得无效。
目前,我的代码可以毫无问题地处理这些无效引用。所有这些指针在库中实际使用之前都会经过验证,因此代码是安全的。
然而,从 Lua 用户的角度来看,这似乎有点令人困惑,因为无法判断该引用是否仍然有效(这不是很重要,但我仍然想改进它).
我想要的是以下内容。我想从 C 迭代 Lua 存储的所有 lightuserdata。如果 lightuserdatum 不再有效,请将其设置为零。这样,下次使用时该变量将有效或为零,为用户提供更好的 API。
有什么办法可以实现这一点吗?我可以从 C all Lua 知道的 lightuserdata 中迭代(无论它们存储在哪里,本地/全局/表等),并修改它们吗?
最佳答案
没有办法从 C 访问局部 lua 变量。因此,即使您确实迭代了某种类型的 lua 对象,您也无法访问至少一个区域(局部变量)。
您可以迭代全局表中的所有内容,如 Max 的回答所示:Loop through all Lua global variables in C++
如果您要针对 lua_islightuserdata 进行测试,然后将 lightuserdata 的值与您要删除的指针进行比较,您应该能够识别出您想要的全局值。
lua_pushglobaltable(L);
lua_pushnil(L);
while (lua_next(L,-2) != 0)
{
if (lua_islightuserdata(L, -1))
{
//TODO: compare against the lightuserdata pointer value you are looking for
void* mypointer = lua_touserdata(state, -1);
name = lua_tostring(L,-2); // Get key(-2) name
//TODO: do whatever with the value; probably set to nil by name in the global table
}
lua_pop(L,1);
}
lua_pop(L,1);
但是,如果您想在表中搜索它,则必须对 lua_istable 进行额外检查,然后以相同的方式递归迭代表的值。
...
else if (lua_istable(L, -1)
{
//TODO: iterate each value in the table searching for lightuserdata
// or tables with further levels of recursion
}
...
但是,我认为在 MyLib 上提供一个名为“isValid”的方法会更直接,该方法在使用该值之前返回该值是否仍然有效。
local ref = MyLib.createObject("some", arguments)
...
local isvalid = MyLib.isValid(ref)
那么您就不会受到本地范围的限制。另外,假设你无论如何都会在你的 lua 代码中进行 nil 检查(看看值是否从你的下面改变了),这在代码方面基本上不需要任何成本。
关于c - 从 C 访问 lightuserdata,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55458114/