战魂小筑

讨论群:309800774 知乎关注:http://zhihu.com/people/sunicdavy 开源项目:https://github.com/davyxu

   :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  257 随笔 :: 0 文章 :: 506 评论 :: 0 Trackbacks

以下代码使用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会有什么影响?

欢迎各位有此经验的讨论

posted on 2012-03-27 10:38 战魂小筑 阅读(1514) 评论(2)  编辑 收藏 引用 所属分类: 脚本技术C++/ 编程语言

评论

# re: luabind使用coroutine时的一处善意提示导致的BUG[未登录] 2012-03-27 15:36 陈梓瀚(vczh)
assert和exception是不一样的。assert是绝对不能发生的错误,exception只是用来替换类似HRESULT这种COM的返回值而已。发生了assert则一定要修改代码使之不发生(对于你的情况就是修改你传入的参数),而exception你可以处理或者不处理。

所以这个不是lua的问题,是你的问题。  回复  更多评论
  

# re: luabind使用coroutine时的一处善意提示导致的BUG 2012-03-27 17:30 战魂小筑
@陈梓瀚(vczh)
大哥,我说了嘛,故意错误而导致的, 把assert跳过就能正确抛出代码中错误信息
如果代码正确,压根不会有assert  回复  更多评论
  


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理