程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> luabind使用coroutine時的一處善意提示導致的BUG

luabind使用coroutine時的一處善意提示導致的BUG

編輯:C++入門知識

以下代碼使用luabind進行lua的coroutine測試
   1: void ScriptManagedChannel::OnServiceInitialize()
   2: {   
   3:     try
   4:     {       
   5:         mThread = lua_newthread( GScriptScriptContext->GetVM() );
   6: 
   7:         luabind::resume_function<void>( mThread, "ScriptMain", this );
   8: 
   9:         Resume();
  10:     }
  11:     catch (std::exception& e)
  12:     {
  13:         const char* ErrorMsg = lua_tostring( GScriptScriptContext->GetVM(), -1 );           
  14:         printf("%s\n", e.what() );
  15:     }
  16: 
  17:    
  18: }
  19: 
  20: void ScriptManagedChannel::Resume( )
  21: {
  22:     luabind::resume<void>( mThread );
  23: }
  24: 
  25: void ScriptManagedChannel::StopTest( )
  26: {
  27:     lua_yield( mThread, 0 );
  28: }
  29: 
  30: 
代碼中, mThread類型為lua_State*類型
GScriptScriptContext->GetVM()是加載了代碼的lua_State*
StopTest為注冊為ScriptManagedChannel類成員函數到lua中的定義
接下來看lua端的測試代碼:
   1: function ScriptMain( Channel )
   2: 
   3:    
   4:     for i = 1, 5 do
   5:    
   6:     print("done", i)
   7:    
   8:     Channel:StopTest( )
   9:    
  10:    
  11:    
  12:     end
  13: end
剛開始,在測試代碼時, lua中有個手誤而造成的錯誤, 導致C++代碼運行到第7行時彈出assert
位於:luabind-0.9.1\luabind\detail\call_function.hpp 第264行,對應以下代碼第13行
   1: ~proxy_function_void_caller()
   2: {
   3:     if (m_called) return;
   4: 
   5:     m_called = true;
   6:     lua_State* L = m_state;
   7: 
   8:     int top = lua_gettop(L);
   9: 
  10:     push_args_from_tuple<1>::apply(L, m_args);
  11:     if (m_fun(L, boost::tuples::length<Tuple>::value, 0))
  12:     {
  13:         assert(lua_gettop(L) == top - m_params + 1);
  14: 
  15: NO_EXCEPTIONS
  16:         throw luabind::error(L);
  17: #else
  18:         error_callback_fun e = get_error_callback();
  19:         if (e) e(L);
  20:    
  21:         assert(0 && "the lua function threw an error and exceptions are disabled."
  22:                 " If you want to handle the error you can use luabind::set_error_callback()");
  23:         std::terminate();
  24: #endif
  25:     }
  26:     // pops the return values from the function call
  27:     stack_pop pop(L, lua_gettop(L) - top + m_params);
  28: }
11行代碼中調用的是lua_resume, 返回的是運行錯誤, 但是被13行的assert擋住了, 無法通過第16行拋出異常被外面捕獲.
因此,嘗試注釋第13行, 再測試, 可以在lua拋出錯誤後, 在棧頂捕獲到coroutine函數resume時報出的錯誤信息.問題解決
 
對於lua的coroutine, 網上資料不多, 這裡有一篇比較詳細的代碼
我比較疑惑的是, 有沒有必要將代碼在dofile或者dobuffer時, 必須傳入newthread出的state? 如果還是傳入原始的state會有什麼影響?
歡迎各位有此經驗的討論

 

摘自  戰魂小築 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved