以下代码使用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会有什么影响?
欢迎各位有此经验的讨论