Ошибка утверждения в Luabind - PullRequest
3 голосов
/ 04 июня 2011

В настоящее время у меня возникают проблемы с использованием Luabind для сопряжения искусственного интеллекта Lua с игрой на C ++.

Я вызываю функцию обновления внутри цикла (один раз за кадр), и эта функция извлекает информацию из функций C ++, зарегистрированных в Luabind.

Моя проблема заключается в следующем: После переменной, непредсказуемого времени, в Luabind возникает ошибка подтверждения, которая вызывает прерывание. Ошибка всегда возникает в /usr/include/luabind/wrapper_base.hpp:124 при спуске внутрь Луа.

У вас есть идеи, что можно сделать? Для моих тестов вызываемые функции в C ++ и в LUA всегда одинаковы.

Подробнее о проблеме:

Содержимое окружает утверждение, которое не удалось в 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);

Точная ошибка

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)

Ответы [ 2 ]

3 голосов
/ 20 февраля 2012

У меня была эта проблема несколько дней назад.В моем конкретном случае неявно созданная таблица Lua, в которой содержались все методы, которые были переопределены в Lua для каждого объекта, собиралась мусором, а базовый объект C ++ - нет.Из-за этого, если вы попытаетесь вызвать функцию-член Lua из объекта C ++, произойдет сбой.

В моем случае решение состояло в том, чтобы сохранить ссылку на таблицу lua в течение всего времени, пока экземпляр C ++ былв живых.Это было так же просто, как добавить поле luabind :: object в класс C ++, а затем установить его при создании экземпляра класса, и оно будет уничтожено при вызове деструктора класса 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_ptr s, потому что тогда сборщик мусора части Lua получает вместе с shared_ptr, но не обязательно с экземпляром C ++, на который ссылается указатель.Если Lua управляет всем экземпляром, тогда я не вижу, как таблица Lua могла быть удалена, пока экземпляр C ++ живет.

1 голос
/ 17 августа 2013

Кажется, вы страдаете от раздельного владения объектом. Обычно это происходит, когда оболочка для класса C ++ неправильно оборачивается вокруг виртуальных методов.

Я сталкивался с этой проблемой раньше, но она исчезла после того, как я тщательно внедрил оболочку. В моей библиотеке мне не нужен обходной путь, упомянутый здесь.

...