问题描述
我试图了解如何使用协例程暂停"脚本,并等待直到完成一些处理后再恢复.
I'm trying to get an understanding of how I can use co-routines to "pause" a script and wait until some processing is done before resuming.
也许我在用错误的方式查看协同例程.但是我的尝试的结构类似于此.
Perhaps I'm looking at co-routines in the wrong way. But my attempt is structured similar to the example given in this answer.
loop.lua
中的循环永远不会达到第二次迭代,因此也永远不会达到退出C代码中正在运行的循环所需的i == 4
条件.如果我没有在loop.lua
中屈服,那么此代码将按预期执行.
The loop in loop.lua
never reaches a second iteration, and hence never reaches the i == 4
condition required to exit the running loop in the C code. If I do not yield in loop.lua
, then this code performs as expected.
main.cpp
#include <lua/lua.hpp>
bool running = true;
int lua_finish(lua_State *) {
running = false;
printf("lua_finish called\n");
return 0;
}
int lua_sleep(lua_State *L) {
printf("lua_sleep called\n");
return lua_yield(L,0);
}
int main() {
lua_State* L = lua_open();
luaL_openlibs(L);
lua_register(L, "sleep", lua_sleep);
lua_register(L, "finish", lua_finish);
luaL_dofile(L, "scripts/init.lua");
lua_State* cL = lua_newthread(L);
luaL_dofile(cL, "scripts/loop.lua");
while (running) {
int status;
status = lua_resume(cL,0);
if (status == LUA_YIELD) {
printf("loop yielding\n");
} else {
running=false; // you can't try to resume if it didn't yield
// catch any errors below
if (status == LUA_ERRRUN && lua_isstring(cL, -1)) {
printf("isstring: %s\n", lua_tostring(cL, -1));
lua_pop(cL, -1);
}
}
}
luaL_dofile(L, "scripts/end.lua");
lua_close(L);
return 0;
}
loop.lua
print("loop.lua")
local i = 0
while true do
print("lua_loop iteration")
sleep()
i = i + 1
if i == 4 then
break
end
end
finish()
添加了赏金,希望能对如何实现这一目标有所帮助.
Added a bounty, to hopefully get some help on how to accomplish this.
推荐答案
从lua_resume
返回的代码2是LUA_ERRRUN
.检查Lua堆栈顶部的字符串以查找错误消息.
Return code 2 from lua_resume
is a LUA_ERRRUN
. Check the string on the top of the Lua stack to find the error message.
类似的模式对我有用,尽管我确实使用了coroutine.yield
而不是lua_yield
,并且我使用的是C语言而不是C ++语言.我不明白为什么您的解决方案行不通
A similar pattern has worked for me, though I did use coroutine.yield
instead of lua_yield
and I'm in C rather than C++. I don't see why your solution wouldn't work
在您的履历表调用中,尚不清楚您是否过度简化了示例,但我会在while循环中进行以下更改:
On your resume call, it's not clear if you're over simplifying for an example, but I'd make the following changes in your while loop:
int status;
status=lua_resume(cL,0);
if (status == LUA_YIELD) {
printf("loop yielding\n");
}
else {
running=false; // you can't try to resume if it didn't yield
// catch any errors below
if (status == LUA_ERRRUN && lua_isstring(cL, -1)) {
printf("isstring: %s\n", lua_tostring(cL, -1));
lua_pop(cL, -1);
}
}
要进行调试,请在运行简历之前添加以下内容.您有一个字符串被压入堆栈中的某个位置:
For debugging, add the following before you run your resume. You've got a string getting pushed on the stack somewhere:
int status;
// add this debugging code
if (lua_isstring(cL, -1)) {
printf("string on stack: %s\n", lua_tostring(cL, -1));
exit(1);
}
status = lua_resume(cL,0);
哦,真可惜,我不敢相信我还没有看到这一点,因为您不能直接产生pcall,所以您不想运行luaL_dofile
,因为据我所知,这是在dofile中发生的事情(5.2将通过它,但我认为您仍然需要lua_resume).切换到此:
Oh good grief, I can't believe I didn't see this already, you don't want to run luaL_dofile
when you're going to yield because you can't yield a pcall directly as best I know, which is what happens in the dofile (5.2 will pass it through, but I think you still need the lua_resume). Switch to this:
luaL_loadfile(cL, "scripts/loop.lua");
这篇关于Lua例程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!