C++中對lua協程和返回值的處理
lua語言中, 在coroutine的resume和yield之間可以相互傳遞參數, 最近研究了下lua_resume和lua_yield 兩個函數, 同樣利用這兩個函數可以通過棧在C++與lua之間很方便的交換數據;這裏給出一個簡單的示例;
1.lua中寫一個協程函數
function CorTest() print("coroutine begin") local re = coroutine.yield(100, "hello c++") // 往棧中傳參數以便C++能獲取 print("lua coroutine continue: " .. re) // 從c中lua_resume傳回來的參數是者的re Stop("call c yield!") // 調用c的掛起函數 print("coroutine continue after yield") print("coroutine end") end
這裏嘗試了lua的yield和C++的lua_yield:
2. 在C++中寫一個掛起函數註冊到lua中使用
static int Stop(lua_State* L) { // 會傳一個參數進來 const char* str = lua_tostring(L,-1); print("C Stop: %s\n", str); //將這個值再次壓入棧中 lua_pushstring(L,str); lua_yield(L,1); assert(0); // 協程恢復後是不會回到這邊的, 而是直接回到lua中Stop()後一句, 原因是C++棧已經釋放 return 0; }
3.這裏直接在C中創建協程:
// 參數corName是在lua中寫的協程函數 lua_State* CreateCoroutine(lua_State* gL, const char* corName) { lua_checkstack(L,10); // 10個是隨便寫的一個數字, 不影響 lua_State* lt = lua_newthread(gL); lua_getglobal(lt, corName); // 協程函數入棧 return lt; }
4.這裏在main函數中進行主要處理:
int main() { // 省略前面的lua初始化代碼 /**....**/ lua_register(L,"Wait",Wait); lua_State* lt = CreateCoroutine(L,"CorTest"); int re = lua_resume(lt, L, 0); // 這次傳0個參數(因爲CorTest沒有參數) if(re != LUA_YIELD) printf("ERROR"); // lua掛起後, 穿回來100, 和hello C++兩個值, 可以lua_gettop(lt)看個數 int rint = luaL_checknumber(lt, -2); const char* str = lua_tostring(lt, -1); printf("stack value: %d, %s\n", rint, str); // ⇒ 100, hello C++ // 這次恢復協程時傳入參數, 參數壓棧, lua中就是對應返回值local re lua_pushstring(lt, " from c++"); re = lua_resume(lt, L, 1); // 掛起後是在Stop()函數中傳入了一個"call c yield!" printf("%s\n",lua_tostring(lt,-1)); re = lua_resume(lt, L, 0); // 這裏無法傳值回去lua了,因爲Stop的棧已經被釋放 ,而是直接運行lua中Stop的後一句 }
輸出結果如下:
coroutine begin
100, hello C++
coroutine contine , from C++
C Stop: call yield
coroutine continue after C yield, from c++
lua end