Luabind 中的断言失败

发布于 2024-11-11 23:36:40 字数 2209 浏览 2 评论 0原文

我目前在使用 Luabind 将 Lua 脚本 AI 与 C++ 游戏连接时遇到问题。

我在循环内调用更新函数(每帧一次),该函数从 Luabind 中注册的 C++ 函数中检索信息。

我的问题如下: 经过一段可变的、不可预测的时间后,Luabind 中出现断言失败,导致中止。 在 /usr/include/luabind/wrapper_base.hpp:124 内部下降时总是出现错误 卢阿。

您知道可以做什么吗? 对于我的测试,C++ 和 LUA 中调用的函数始终相同。

有关该问题的更多详细信息:

The content arround the assertion that failed inwrapper_base.hpp

typedef typename boost::mpl::if_<boost::is_void<R>, luabind::detail::proxy_member_void_caller<boost::tuples::tuple<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS, _)> >
, luabind::detail::proxy_member_caller<R, boost::tuples::tuple<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS, _)> > >::type proxy_type;

// Comments removed

lua_State* L = m_self.state();
m_self.get(L);
assert(!lua_isnil(L, -1));
detail::do_call_member_selection(L, name);

if (lua_isnil(L, -1))
  {
    lua_pop(L, 1);
    throw std::runtime_error("Attempt to call nonexistent function");
  }

// push the self reference as the first parameter
m_self.get(L);

// now the function and self objects
// are on the stack. These will both
// be popped by pcall
return proxy_type(L, args);

确切的错误

bomberman: /usr/include/luabind/wrapper_base.hpp:124: typename boost::mpl::if_<boost::is_void<T>, luabind::detail::proxy_member_void_caller<boost::tuples::tuple<boost::tuples::null_type,       boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type,
boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type> >, luabind::detail::proxy_member_caller<R, boost::tuples::tuple<boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type,
boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type> > >::type luabind::wrap_base::call(const char*, luabind::detail::type_<Derived>*) const [with R = void]:
Assertion `!(lua_type(L, (-1)) == 0)' failed.
Aborted (core dumped)

I am currently having problems using Luabind to interface a Lua scripted AI with a C++ game.

I call an update function inside a loop (once per frame) and this function retrieves informations from C++ functions registered in Luabind.

My problem is as follows :
After a variable, non predictible time, there is an assertion failure in Luabind wich causes an abort.
The error always occurs into /usr/include/luabind/wrapper_base.hpp:124 while descending inside
the Lua.

Do you have any idea on what can do that ?
For my tests, the called functions in C++ and in LUA are always the same.

More details about the problem :

The content arround the assertion that failed in wrapper_base.hpp

typedef typename boost::mpl::if_<boost::is_void<R>, luabind::detail::proxy_member_void_caller<boost::tuples::tuple<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS, _)> >
, luabind::detail::proxy_member_caller<R, boost::tuples::tuple<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS, _)> > >::type proxy_type;

// Comments removed

lua_State* L = m_self.state();
m_self.get(L);
assert(!lua_isnil(L, -1));
detail::do_call_member_selection(L, name);

if (lua_isnil(L, -1))
  {
    lua_pop(L, 1);
    throw std::runtime_error("Attempt to call nonexistent function");
  }

// push the self reference as the first parameter
m_self.get(L);

// now the function and self objects
// are on the stack. These will both
// be popped by pcall
return proxy_type(L, args);

The exact error

bomberman: /usr/include/luabind/wrapper_base.hpp:124: typename boost::mpl::if_<boost::is_void<T>, luabind::detail::proxy_member_void_caller<boost::tuples::tuple<boost::tuples::null_type,       boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type,
boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type> >, luabind::detail::proxy_member_caller<R, boost::tuples::tuple<boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type,
boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type> > >::type luabind::wrap_base::call(const char*, luabind::detail::type_<Derived>*) const [with R = void]:
Assertion `!(lua_type(L, (-1)) == 0)' failed.
Aborted (core dumped)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

呆头 2024-11-18 23:36:40

几天前我遇到了这个问题。在我的特定情况下,隐式创建的 Lua 表保存了 Lua 中为每个对象重写的所有方法,该表正在被垃圾收集,而底层 C++ 对象则不然。因此,如果您尝试从 C++ 对象调用 Lua 成员函数,将会失败。

在我的例子中,解决方案是只要 C++ 实例处于活动状态,就保持对 lua 表的引用处于活动状态。这就像向 C++ 类添加一个 luabind::object 字段一样简单,然后在实例化该类时设置它,当调用 C++ 类的析构函数时它将被销毁,因此在大多数情况下您不必担心内存泄漏。我的代码现在看起来像这样:

class LuaC : public BaseC, public luabind::wrap_base {
    private:
        luabind::object _self; //retain a reference to the Lua part of this object so it doesn't get gc'd
    public:
        void setSelf(luabind::object nSelf) { _self=nSelf; }
};
//expose LuaC including the method setSelf
// ...

(BaseC 是你正在包装的 C++ 类)

然后从 Lua 中,每当你实例化 LuaC 的实例时,调用 setSelf 并将 self 作为附加参数传递,

c = LuaC()
c:setSelf(self)

如果没有简化这一点并将其全部放在 LuaC 构造函数中的方法,这样就不容易出错(即,您不必担心每次都调用 setSelf)。但 LuaBind 的文档相当浅薄,所以我找不到任何方法来做到这一点。

另外,我相信发生这个问题的唯一方法是,如果你告诉 Luabind 仅使用像 shared_ptrs 这样的引用,因为这样 Lua 部分会与 shared_ptr 一起被垃圾收集,但不会必然是指针引用的 C++ 实例。如果 Lua 管理整个实例,那么我不明白 Lua 表如何在 C++ 实例存在时被删除。

I had this problem a few days ago. In my particular case, the implicitly created Lua table that held all the methods that had been overridden in Lua for each object was being garbage collected, while the underlying C++ object was not. Because of this, if you tried to call a Lua member function from a C++ object, it would fail.

The solution in my case was to keep a reference to the lua table alive as long as the C++ instance was alive. That was as simple as adding a luabind::object field to the C++ class and then setting it when you instantiate the class and it will be destroyed when the C++ class's destructor is called, so in most cases you won't have to worry about memory leaks. My code looks something like this now:

class LuaC : public BaseC, public luabind::wrap_base {
    private:
        luabind::object _self; //retain a reference to the Lua part of this object so it doesn't get gc'd
    public:
        void setSelf(luabind::object nSelf) { _self=nSelf; }
};
//expose LuaC including the method setSelf
// ...

(BaseC is the C++ class you're wrapping)

Then from Lua, whenever you instantiate an instance of LuaC, call setSelf and pass self as an additional argument

c = LuaC()
c:setSelf(self)

I would be surprised if there isn't a way to simplify this and put it all inside the LuaC constructor so that it's less error-prone (ie so you don't have to worry about calling setSelf every time). But the documentation for LuaBind is rather shallow, so I couldn't find any way to do this.

Also, I believe the only way for this problem to occur is if you're telling Luabind to only use references like shared_ptrs, because then the Lua part get's garbage collected, along with the shared_ptr, but not necessarily the C++ instance referenced by the pointer. If Lua is managing the entire instance, then I don't see how the Lua table could get deleted while the C++ instance lives on.

绝影如岚 2024-11-18 23:36:40

您似乎正遭受对象所有权分割的困扰。当 C++ 类的包装器未正确包装虚拟方法时,通常会发生这种情况。

我以前遇到过这个问题,但在我仔细实现包装器后它就消失了。在我的库中,我不需要这里提到的解决方法。

It seems you are suffering from split ownership of the object. This usually happens when the wrapper for a C++ class does not properly wrap around virtual methods.

I encountered this issue before but it went away after I carefully implemented the wrapper. In my library, I don't need the workaround mentioned here.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文