2011-08-26 13 views
7

私は、コルーチンを使ってスクリプトを "一時停止"し、再開する前に何らかの処理が完了するまで待つ方法を理解しようとしています。Luaの共同作業

おそらく私は間違った方法でコルーチンを見ています。しかし、私の試みは、answerに与えられた例と同様に構成されています。

loop.luaのループは決して2回目の繰り返しに達しないため、実行中のループをCコードから終了するのに必要な条件は決してi == 4に達しません。私が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

lua_resumeのリターンコード2は、LUA_ERRRUNです。エラーメッセージを見つけるには、Luaスタックの上部にある文字列を確認してください。

lua_yieldの代わりにcoroutine.yieldを使用しましたが、私はC++ではなく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

エラーコード2は、レジュームコードが連続して実行されている場合にのみ発生します(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

私はそのようなコードで

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のコルーチンをいじりされた最後の時間は、あなたがコルーチンとしてファイルを読み込むことができませんでしたが?代わりにfunctionを使用します。スタックの最上部まで選択する必要があります。

+1

Luaスクリプトにコルーチンを作成する必要はなく、 'lua_newthread'呼び出しはC/C++でそれを行います。私は何の問題もなく自分でそれを使用します。 – BMitch

+0

実際には私はraw_programをロードしません。私は私のポストからそれをカットする必要があります。しかし、はい、私は参照してください。問題は、コルーチンを再開することです。それらを起動しません。元の投稿を慎重に読むべきです – yatagarasu

+0

あなたの例で 'lua_newthread'を使っているのを見ただけです。しかし、ええ、OPはコルーチンを生成した後に問題があります。 – BMitch

関連する問題