Совлокальные занятия Lua
7 dcousens [2011-08-26 17:42:00]
Я пытаюсь понять, как я могу использовать совлокальные подпрограммы, чтобы "приостановить" script и дождаться завершения какой-либо обработки до возобновления.
Возможно, я смотрю на совлокальные подпрограммы неправильно. Но моя попытка структурирована аналогично примеру, приведенному в этом .
Цикл в loop.lua
никогда не достигает второй итерации и, следовательно, никогда не достигает условия i == 4
, необходимого для выхода из цикла работы кода C. Если я не выхожу в loop.lua
, тогда этот код работает как ожидалось.
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()
EDIT: добавлена щедрость, чтобы, надеюсь, получить некоторую помощь в том, как это сделать.
c++ coroutine scripting lua
2 ответа
2 Решение BMitch [2011-08-26 23:00:00]
Код возврата 2 из lua_resume
равен LUA_ERRRUN
. Проверьте строку в верхней части стека Lua, чтобы найти сообщение об ошибке.
Аналогичный шаблон работал у меня, хотя я использовал coroutine.yield
вместо lua_yield
, а я нахожусь на C, а не на С++. Я не понимаю, почему ваше решение не работает.
В вашем повторном вызове не ясно, если вы упростите пример, но я внес бы следующие изменения в цикл while:
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);
}
}
Изменить 2:
Для отладки добавьте следующее, прежде чем запускать свое резюме. Вы где-то нажимаете строку:
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);
Изменить 3:
О, хорошо, я не могу поверить, что я этого не видел, вы не хотите запускать luaL_dofile
, когда вы собираетесь уступить, потому что вы не можете дать pcall напрямую, насколько я знаю, что происходит в dofile (5.2 пройдет через него, но я думаю, что вам все равно нужен lua_resume). Переключитесь на:
luaL_loadfile(cL, "scripts/loop.lua");
0 yatagarasu [2011-08-30 18:57:00]
В прошлый раз, когда я возился с Lua coroutines, я закончил с таким кодом
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");