2011-08-26 2 views
7

Я пытаюсь понять, как я могу использовать совместные подпрограммы, чтобы «приостановить» сценарий и дождаться завершения обработки до возобновления.Lua co-routines

Возможно, я смотрю на совместные процедуры неправильным образом. Но моя попытка структурирована аналогично примеру, приведенному в этом answer.

Петля в 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: Добавлен Баунти, мы надеемся получить некоторую помощь о том, как достичь этого.

ответ

2

Код возврата 2 от lua_resume является LUA_ERRRUN. Проверьте строку в верхней части стека Lua, чтобы найти сообщение об ошибке.

Аналогичная модель работала для меня, хотя я использовал coroutine.yield вместо lua_yield, а я нахожусь на C, а не на C++. Я не понимаю, почему ваше решение не будет работать

На вашем резюме разговора, это не ясно, если вы более упрощая для примера, но я хотел бы сделать следующие изменения в ваше время цикла:

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); 
    } 
} 

Edit 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); 

Edit 3:

О хорошее горе, я не могу поверить, что я не видел этого уже, вы не хотите запустите luaL_dofile, когда вы собираетесь уступить, потому что вы не можете дать pcall напрямую, насколько я знаю, что происходит в dofile (5.2 пройдет через него, но я думаю, что вам все еще нужен lua_resume). Переключитесь на это:

luaL_loadfile(cL, "scripts/loop.lua"); 
+0

Код ошибки 2 возникает только при последовательном запуске кода резюме (более одного, без другого выхода). Любая другая ошибка, которую я получаю, это: «попытка вызвать строковое значение».Поп-код: 'if (lua_isstring (cL, -1)) { \t \t printf (" isstring:% s \ n ", lua_tostring (cL, -1)); \t \t lua_pop (cL, -1); \t} ' – dcousens

+0

« попытка вызвать строку »означает, что что-то еще находится в стеке, отличном от вашей подпрограммы, возможно, сообщение об ошибке. И когда возобновление заканчивается с возвратом 0, процедура выполняется, и вы больше не можете ее возобновить, она больше не находится в стеке. Вы можете возобновить повтор только в том случае, если в последний раз вы получили доход или нажали новую процедуру в стеке. – BMitch

+0

Как я могу получить сообщение об ошибке, если не через код выше? – dcousens

0

Последний раз я был Мессинг с 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"); 
+1

Не нужно создавать сопрограммы в сценарии Lua, вызов 'lua_newthread' делает это на C/C++. Я сам использую его без каких-либо проблем. – BMitch

+0

На самом деле я не загружаю raw_program. Я должен отрезать его от моего поста. Но да, я вижу. Проблема заключается в возобновлении сопрограммы. не начинать их. должен внимательно прочитать оригинальное сообщение – yatagarasu

+0

Только что увидел, что вы используете 'lua_newthread' в вашем примере. Но да, у ОП есть проблемы после получения сопрограммы. – BMitch

Смежные вопросы