1

如果对导出的类(对象)的成员函数调用是针对有效对象的,luabind 是否有可能进行检查?

假设我有一个使用 luabind 暴露给 lua 的名为 Actor 的类。我从 C++ 调用一个 lua 函数,并以一个 actor 对象作为参数。现在在函数完成之前,脚本编写会将actor对象放在全局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 检查在这里没有帮助,这可以在 luabinds 网站上检查吗?这些函数使用 lua_pcall(....) 执行,堆栈跟踪显示 luabinds call.hpp results = maybe_yield(L, lua_gettop(L) - arguments, (Policies*)0) 处的错误;

如果没有,是否有另一种解决方案来确保编写脚本的人无法创建这些问题?

4

2 回答 2

2

现在在函数完成之前,脚本编写会将actor对象放在全局lua引用中,以便稍后访问。

那就是你的问题来自哪里。如果您希望 Lua 代码拥有该对象(即保留该对象的存在),那么您需要使用 Luabind 机制告诉 Luabind 您想要这样做。否则,如果你传递一个指向某个 Lua 函数的指针,Luabind 将假定该函数不会试图获得它的所有权。

如果您希望在 Lua 和 Luabind 之间共享所有权,那么您应该将对象包装在 a 中boost::shared_ptr,并使用 Luabind 的智能指针机制来执行此操作。

您也可以简单地更好地隔离您的脚本。如果您有一些对特定参与者进行操作的脚本,那么该脚本及其包含的任何函数都应该与对象一起被销毁(即:丢失对它的所有引用)。这需要在 C++ 端进行适当的编码纪律。它还要求您使用 Lua 环境正确封装脚本的每个实例,这样它们就不能通过全局变量偷偷摸摸。最后,您需要让 C++ 完全控制何时调用脚本以及何时不调用脚本。

否则,所有权是您的脚本编写者必须了解和小心的事情。他们不能像对待任何旧的 Lua 值一样对待 C++ 参数。


如果您无法进行严格的编程实践或不切实际,那么您只需不将实际的 C++ 对象传递给 Lua。相反,您需要向 Lua 传递一些代理对象,它是对原始对象的引用。boost::weak_ptr 是这样一个对象的一个​​很好的例子(尽管你不会将它完全传递给 Lua)。代理会将调用转发到实际对象。如果对象已被删除,代理将检测到这一点并失败或不做任何事情。

于 2013-01-25T22:46:20.023 回答
0

我通过以下方式解决了我的问题:

当我要删除一个对象时,我会遍历 C++ 中的所有 lua 函数(我将它们放在一个列表中,它们每个都绑定到特定的 actor 对象)。然后我检查每个上值(全局/本地变量可访问一个函数) - 然后我将用户数据指针与我即将删除的对象进行比较 - 如果它们匹配(及其类)并且 NIL 上值。或者,我可以删除那个有问题的功能,因为它无论如何都不能正常工作了。

所以下一次调用函数时,我只是得到一个软 lua 错误“试图访问 xxx 一个 nil 值......” - 没有更多的访问冲突。

I know people would say "dont use lua_getupvalue/lua_setupvalue - they are only for debugging!" - but there is actually no documented or spoken side effect - and in my case its perfectly safe and works well - also there isnt the issue with left over proxy objects i could not delete.

于 2013-01-31T11:05:12.397 回答