Lua 协程
2017-5-23 11:51:50
收藏:0
阅读:115
评论:2
我试图了解如何使用协同程序来“暂停”一个脚本,等待一些处理完成后再继续执行。
也许我没有正确理解协同程序的用法。但是我的尝试类似于此答案中给出的示例。
在loop.lua
中的循环从未达到第二次迭代,因此从未达到C代码中需要退出运行循环的i == 4
条件。如果我在loop.lua
中不yield
,则此代码将按预期执行。
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()
编辑:添加了一份悬赏,希望能够得到一些关于如何实现这一目标的帮助。
原文链接 https://stackoverflow.com/questions/7206411
点赞
stackoverflow用户264358
上次我在用 Lua 协程时,最后得到了这样的代码:
const char *program =
"function hello()\n"
" io.write(\"Hello world 1!\")\n"
" io.write(\"Hello world 2!\")\n"
" io.write(\"Hello world 3!\")\n"
"end\n"
"function hate()\n"
" io.write(\"Hate world 1!\")\n"
" io.write(\"Hate world 2!\")\n"
" io.write(\"Hate world 3!\")\n"
"end\n";
const char raw_program[] =
"function hello()\n"
" io.write(\"Hello World!\")\n"
"end\n"
"\n"
"cos = {}\n"
"\n"
"for i = 0, 1000, 1 do\n"
" cos[i] = coroutine.create(hello)\n"
"end\n"
"\n"
"for i = 0, 1000, 1 do\n"
" coroutine.resume(cos[i])\n"
"end";
int _tmain(int argc, _TCHAR* argv[])
{
lua_State *L = lua_open();
lua_State *Lt[1000];
global_State *g = G(L);
printf("Lua memory usage after open: %d\n", g->totalbytes);
luaL_openlibs(L);
printf("Lua memory usage after openlibs: %d\n", g->totalbytes);
lua_checkstack(L, 2048);
printf("Lua memory usage after checkstack: %d\n", g->totalbytes);
//lua_load(L, my_lua_Reader, (void *)program, "code");
luaL_loadbuffer(L, program, strlen(program), "line");
printf("Lua memory usage after loadbuffer: %d\n", g->totalbytes);
int error = lua_pcall(L, 0, 0, 0);
if (error) {
fprintf(stderr, "%s", lua_tostring(L, -1));
lua_pop(L, 1);
}
printf("Lua memory usage after pcall: %d\n", g->totalbytes);
for (int i = 0; i < 1000; i++) {
Lt[i] = lua_newthread(L);
lua_getglobal(Lt[i], i % 2 ? "hello" : "hate");
}
printf("Lua memory usage after creating 1000 threads: %d\n", g->totalbytes);
for (int i = 0; i < 1000; i++) {
lua_resume(Lt[i], 0);
}
printf("Lua memory usage after running 1000 threads: %d\n", g->totalbytes);
lua_close(L);
return 0;
}
似乎你不能将文件加载为协程,但可以使用函数代替。并且应该将它选择到堆栈顶部。
lua_getglobal(Lt[i], i % 2 ? "hello" : "hate");
2011-08-30 15:57:21
评论区的留言会收到邮件通知哦~
推荐文章
- 如何在roblox studio中1:1导入真实世界的地形?
- 求解,lua_resume的第二次调用继续执行协程问题。
- 【上海普陀区】内向猫网络招募【Skynet游戏框架Lua后端程序员】
- SF爱好求教:如何用lua实现游戏内调用数据库函数实现账号密码注册?
- Lua实现网站后台开发
- LUA错误显式返回,社区常见的规约是怎么样的
- lua5.3下载库失败
- 请问如何实现文本框内容和某个网页搜索框内容连接,并把网页输出来的结果反馈到另外一个文本框上
- lua lanes多线程使用
- 一个kv数据库
- openresty 有没有比较轻量的 docker 镜像
- 想问一下,有大佬用过luacurl吗
- 在Lua执行过程中使用Load函数出现问题
- 为什么 neovim 里没有显示一些特殊字符?
- Lua比较两个表的值(不考虑键的顺序)
- 有个lua简单的项目,外包,有意者加微信 liuheng600456详谈,最好在成都
- 如何在 Visual Studio 2022 中运行 Lua 代码?
- addEventListener 返回 nil Lua
- Lua中获取用户配置主目录的跨平台方法
- 如何编写 Lua 模式将字符串(嵌套数组)转换为真正的数组?
从
lua_resume
返回代码2是一个LUA_ERRRUN
。检查Lua堆栈顶部的字符串以查找错误消息。我使用了类似的模式,但我使用了
coroutine.yield
而不是lua_yield
,而且我使用的是C而不是C ++。我不明白你的解决方案为什么不起作用。在您的
resume
调用中,如果您过于简化示例,那么在while循环中进行以下更改:int status; status=lua_resume(cL,0); if (status == LUA_YIELD) { printf("loop yielding\n"); } else { running=false; // 无法恢复,如果没有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); } }
编辑2:
为了调试,请在运行resume之前添加以下内容。您有一个字符串在某个地方被推到堆栈上:
int status; // 添加此调试代码 if (lua_isstring(cL, -1)) { printf("string on stack: %s\n", lua_tostring(cL, -1)); exit(1); } status = lua_resume(cL,0);
编辑3:
天啊,我不敢相信我没有早点看到这个,当您要进行yield时,您不应该运行
luaL_dofile
,因为我所知道的最好的办法是无法直接yield pcall,这就是在dofile中发生的(5.2将通过,但我认为仍然需要lua_resume)。转换为以下内容:luaL_loadfile(cL, "scripts/loop.lua");