2011-06-04 89 views
3

我目前在使用Luabind將Lua腳本化AI與C++遊戲進行接口方面存在問題。Luabind中的聲明失敗

我在循環內調用一個更新函數(每幀一次),該函數從Luabind中註冊的C++函數中檢索信息。

我的問題如下: 經過一個變量,不可預測的時間,在Luabind中有一個斷言失敗導致中止。 錯誤總是出現在/usr/include/luabind/wrapper_base.hpp:124中,而在Lua的 內下降。

你有什麼想法可以做什麼? 對於我的測試,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) 
+1

對答案感興趣 – Intrepidd 2011-06-04 12:49:58

+0

請您在系統上發佈wrapper_base:124的幾行內容嗎?也是完整的錯誤信息文本。 – 2011-06-04 16:10:11

+0

你解決了嗎?我有完全相同的錯誤。 – Ponkadoodle 2012-02-16 18:42:16

回答

3

我前幾天有這個問題。在我的特殊情況下,隱式創建的Lua表保留了Lua中爲每個對象覆蓋的所有方法,而這些方法被垃圾回收,而底層的C++對象則沒有。因此,如果您嘗試從C++對象調用Lua成員函數,則會失敗。

在我的情況下,解決方案是保持對lua表的引用,只要C++實例處於活動狀態即可。這很簡單,只需在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並通過自身作爲附加參數

c = LuaC() 
c:setSelf(self) 

如果沒有簡化這一點,並把它所有的LuaC構造函數內部,這是一個方式,我會感到驚訝,更不容易出錯(例如,所以你不必擔心通話setSelf每次)。但LuaBind的文檔很淺,所以我找不到任何方法來做到這一點。

而且,我相信,出現這一問題的唯一途徑是,如果你告訴Luabind只使用像shared_ptr S變量,因爲那時的Lua部分獲取的垃圾收集,shared_ptr的一起,但不一定是C++由指針引用的實例。如果Lua正在管理整個實例,那麼當C++實例繼續運行時,我不會看到Lua表如何被刪除。

1

看起來你正在遭受對象的分割所有權。這通常發生在C++類的包裝器沒有正確包裝虛擬方法的時候。

我之前遇到過這個問題,但是在我仔細實現了包裝後,它就消失了。在我的圖書館中,我不需要這裏提到的解決方法。

+0

您能否介紹一下包裝中的一些缺陷會導致這些類型的問題? – 2017-06-24 22:24:40