luabind:从Lua访问一个已失效的C++对象会导致访问冲突。
luabind是否可以检查导出类(对象)的成员函数调用是否针对有效对象?
假设我有一个名为Actor的类,使用luabind将其暴露给lua。我正在使用一个actor对象作为参数从C++调用lua函数。现在,在函数完成之前,脚本编写器会将演员对象放在全局lua引用中,以便以后访问。
稍后,在C++端删除了actor对象,调用另一个函数尝试访问已失效的actor对象(它的任何方法)-显然,由于它已被删除,结果会导致崩溃(访问冲突)。
示例:
local myObjRef = nil
function doSomethingWithActor(actor)
-- save, still valid object
actor:Say("hello")
myObjRef = actor
end
function calledAfterActorWasDeleted()
--- will crash if the c++ object has been deleted meanwhile, works fine if it still exists
myObjRef:Say("Crash...")
end
在这种情况下,NIL检查无效,这是否可以在luabind中检查?使用lua_pcall(....)执行函数,并且堆栈跟踪显示错误在luabind调用.hpp results = maybe_yield(L,lua_gettop(L) -参数,(Policies*)0)。
如果不行,是否有其他解决方案,以确保编写脚本的人无法创建这些问题?
我用以下方法解决了我的问题:
当我要删除一个对象时,我遍历所有从C ++绑定到特定actor对象的lua函数(我将它们保存在列表中)。然后我检查每个upvalue(函数可访问的全局/局部变量) - 然后将userdata指针与我要删除的对象进行比较 - 如果它们匹配(并且它们的类是NIL upvalue),则它们匹配(并且它们的类是NIL upvalue)。可选地,我可以删除那个有问题的函数,因为它将不再起作用。
因此,下一次调用该函数时,我只会获得“尝试访问xxx nil值…”的软lua错误 - 不再存在访问冲突。
我知道人们会说“不要使用lua_getupvalue / lua_setupvalue - 它们只用于调试!” - 但实际上没有记录或口头副作用 - 在我的情况下,这是完全安全和有效的 - 并且没有剩余代理对象的问题我无法删除。
- 如何将两个不同的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中获取用户配置主目录的跨平台方法
现在,在函数结束之前,一个脚本会将演员对象放置在全局 Lua 引用中以供以后访问。
这就是你出现问题的原因所在。如果你希望 Lua 代码 拥有 这个对象(即保留该对象的存在),则需要使用 Luabind 机制告诉 Luabind 你想要这样做。否则,如果你将指针传递给某个 Lua 函数,Luabind 将假定该函数不会试图拥有它。
如果你希望所有权在 Lua 和 Luabind 之间 _共享_,则应将对象封装在
boost::shared_ptr中,并使用 Luabind 的智能指针机制来实现这一点。你也可以简单地更好地隔离脚本。如果你有一些操作特定演员的脚本,那么该脚本及其包含的任何函数应该随着对象一起被销毁(即失去对它的所有引用)。这需要在 C++ 方面有适当的编程纪律。它还需要使用 Lua 环境来适当地封装每个脚本的实例,以便它们不能通过全局变量偷偷传递任何东西。最后,你需要使 C++ 完全控制何时调用脚本和何时不调用。
否则,所有权就是你的脚本编写者需要知道并小心处理的事情。他们不能将 C++ 参数视为任何老的 Lua 值。
如果无法或不切实际地实行有纪律的编程实践,则必须不传递 Lua 实际的 C++ 对象。相反,你需要传递 Lua 一些代理对象,该对象是对原始对象的引用。
boost::weak_ptr是这样一个对象的良好示例(虽然你不会将它确切地传递给 Lua)。代理会将调用转发到实际对象。如果对象已被删除,则代理将检测到这一点并失败或不执行任何操作或其他操作。