void _event(state_stack *stack, SDL_Event *evt) { state_desc *top = (state_desc*) table_ind(stack, stack->m_len-1); _talk_state *st = (_talk_state*) top->m_pData; input_event mapped; int i, err; switch (st->m_iState) { case _STARTED: err = lua_resume(st->m_pThread, nullptr, 0); if (_util_lua_done(err, top)) { return; } _event(stack, evt); break; case _WAIT_CHOICE: i = menu_input(st->m_pChoices, evt); if (i == -1) { return; } lua_pushnumber(st->m_pThread, i + 1); err = lua_resume(st->m_pThread, nullptr, 1); if (_util_lua_done(err, top)) { return; } break; case _WAIT_ANY: input_get_event(evt, &mapped); if (mapped.m_iType == IN_OFF || evt->type == SDL_MOUSEBUTTONUP) { err = lua_resume(st->m_pThread, nullptr, 0); if (_util_lua_done(err, top)) { return; } } break; case _STOPPED: top->m_isDead = true; break; } }
bool EmbeddedGamePanel::_resume(lua_State *L, int iNArgs, int iNRes) { // L will be an event handling coroutine. // Start by sending the event to the coroutine by resuming it with the // event arguments. bool bGood = true; if(lua_resume(L, iNArgs) != LUA_YIELD) { // Error occured during event processing. bGood = false; // Transfer the error details to m_Lthread int iNTransfer = lua_gettop(L); if(lua_status(L) >= LUA_ERRRUN) iNTransfer = 1; lua_checkstack(m_Lthread, iNTransfer); lua_xmove(L, m_Lthread, iNTransfer); lua_settop(L, 0); // Allow m_Lthread to respond to the error in an appropriate way lua_resume(m_Lthread, iNTransfer); } else { // Event processed without errors, and will have returned true if // a redraw needs to occur. if(lua_toboolean(L, -1) != 0) { Refresh(false); } } // Leave L with the desired number of return values. lua_settop(L, iNRes); return bGood; }
int main() { // Lua 를 초기화 한다. lua_State* L = lua_open(); // Lua 기본 함수들을 로드한다.- print() 사용 luaopen_base(L); // Lua 문자열 함수들을 로드한다.- string 사용 luaopen_string(L); // TestFunc 함수를 Lua 에 등록한다. lua_tinker::def(L, "TestFunc", &TestFunc); lua_tinker::def(L, "TestFunc2", &TestFunc2); // TestClass 클래스를 Lua 에 추가한다. lua_tinker::class_add<TestClass>(L, "TestClass"); // TestClass 의 함수를 등록한다. lua_tinker::class_def<TestClass>(L, "TestFunc", &TestClass::TestFunc); lua_tinker::class_def<TestClass>(L, "TestFunc2", &TestClass::TestFunc2); // TestClass 를 전역 변수로 선언한다. TestClass g_test; lua_tinker::set(L, "g_test", &g_test); // sample3.lua 파일을 로드한다. lua_tinker::dofile(L, "sample6.lua"); // Thread 를 시작한다. lua_newthread(L); lua_pushstring(L, "ThreadTest"); lua_gettable(L, LUA_GLOBALSINDEX); // Thread 를 시작한다. printf("* lua_resume() 호출\n"); lua_resume(L, 0); // Thread 를 다시 시작한다. printf("* lua_resume() 호출\n"); lua_resume(L, 0); // Thread 를 다시 시작한다. printf("* lua_resume() 호출\n"); lua_resume(L, 0); // Thread 를 다시 시작한다. printf("* lua_resume() 호출\n"); lua_resume(L, 0); // Thread 를 다시 시작한다. printf("* lua_resume() 호출\n"); lua_resume(L, 0); // 프로그램 종료 lua_close(L); return 0; }
inline int lua_resume_compat(lua_State *L, int nargs) { if (nargs < 0) { nargs = 0; } #if LUA_VERSION_NUM >= 502 return lua_resume(L, 0, nargs); #else return lua_resume(L, nargs); #endif }
int resume_impl(lua_State *L, int nargs, int) { #if LUA_VERSION_NUM >= 501 // Lua 5.1 added LUA_YIELD as a possible return value, // this was causing crashes, because the caller expects 0 on success. int res = lua_resume(L, nargs); return (res == LUA_YIELD) ? 0 : res; #else return lua_resume(L, nargs); #endif }
bool LuaScript::resume() { assert(nbArgs >= 0); assert(mCurrentThread); const Context *previousContext = mContext; mContext = &mCurrentThread->getContext(); const int tmpNbArgs = nbArgs; nbArgs = -1; #if LUA_VERSION_NUM < 502 int result = lua_resume(mCurrentState, tmpNbArgs); #else int result = lua_resume(mCurrentState, nullptr, tmpNbArgs); #endif if (result == 0) // Thread is done { if (lua_gettop(mCurrentState) > 0) LOG_WARN("Ignoring values returned by script thread!"); } else if (result == LUA_YIELD) // Thread has yielded { if (lua_gettop(mCurrentState) > 0) LOG_WARN("Ignoring values passed to yield!"); } else // Thread encountered an error { // Make a traceback using the debug.traceback function lua_getglobal(mCurrentState, "debug"); lua_getfield(mCurrentState, -1, "traceback"); lua_pushvalue(mCurrentState, -3); // error string as first parameter lua_pcall(mCurrentState, 1, 1, 0); LOG_WARN("Lua Script Error:" << std::endl << lua_tostring(mCurrentState, -1)); } lua_settop(mCurrentState, 0); mContext = previousContext; const bool done = result != LUA_YIELD; if (done) { // Clean up the current thread (not sure if this is the best place) delete mCurrentThread; } mCurrentThread = 0; mCurrentState = mRootState; return done; }
static int ts_lua_schedule_handler(TSCont contp, TSEvent ev, void *edata) { lua_State *L; ts_lua_cont_info *ci; ts_lua_coroutine *crt; int event, n, ret; ts_lua_http_ctx *actx; ts_lua_main_ctx *main_ctx; event = (int)ev; TSDebug(TS_LUA_DEBUG_TAG, "getting actx and other info"); actx = (ts_lua_http_ctx *)TSContDataGet(contp); TSDebug(TS_LUA_DEBUG_TAG, "getting http_Ctx"); ci = &actx->cinfo; crt = &ci->routine; main_ctx = crt->mctx; L = crt->lua; ret = 0; TSMutexLock(main_ctx->mutexp); ts_lua_set_cont_info(L, ci); if (event == TS_LUA_EVENT_COROUTINE_CONT) { TSDebug(TS_LUA_DEBUG_TAG, "event is coroutine_cont"); n = (intptr_t)edata; ret = lua_resume(L, n); } else { TSDebug(TS_LUA_DEBUG_TAG, "event is not coroutine_cont"); n = lua_gettop(L); ret = lua_resume(L, n - 1); } if (ret == LUA_YIELD) { TSMutexUnlock(main_ctx->mutexp); goto done; } if (ret != 0) { TSError("[ts_lua] lua_resume failed: %s", lua_tostring(L, -1)); } lua_pop(L, lua_gettop(L)); TSMutexUnlock(main_ctx->mutexp); ts_lua_destroy_async_ctx(actx); done: return 0; }
bool resume(lua_State * L, int nargs) { #if LUA_VERSION_NUM < 502 int result = lua_resume(L, nargs); #else int result = lua_resume(L, nullptr, nargs); #endif if (result == LUA_YIELD) return false; if (result == 0) return true; check_result(L, result); lean_unreachable(); return true; }
int task_run(task_id tid, lua_State *L, message_t *m) { task_t *t = task_ref(tid); if (!t) return ERR_INVAL; task_set_current(tid); int rc = 0; int count; switch (t->status) { case ready: if (!m) { t->status = finished; break; } t->L = lua_newthread(L); count = lua_decodemessage(t->L, m) - 1; msg_destroy(m); t->status = running; STACK(t->L,"Resume from ready %f\n",t->id); rc = lua_resume(t->L, count); break; case suspended: count = m ? lua_decodemessage(t->L, m) : 0; if (m) msg_destroy(m); t->status = running; STACK(t->L,"Resume from suspended %f\n",t->id); rc = lua_resume(t->L, count); break; default: break; } if (rc == LUA_ERRRUN) { INFO("Error code %d",rc); t->status = error; STACK(t->L,"Error running task"); } else if (rc == LUA_YIELD) { STACK(t->L,"YIELDED (ref = %d)",t->ref_count); t->status = suspended; // TODO YIELD } else if (rc == 0) { STACK(t->L,"QUITTED (ref = %d)",t->ref_count); t->status = finished; } // TODO task->coro = get current coroutine task_set_current(0); task_free(tid); // TODO handle rc return SUCCESS; }
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AvHTeamNumber AvHLUA::OnVictoryCheck() { // GC TEST //int limit = lua_getgcthreshold(this->mGlobalContext); /* previous limit */ //lua_setgcthreshold(this->mGlobalContext, 0); /* force a GC cicle */ //lua_setgcthreshold(this->mGlobalContext, limit); if (this->mLoaded && this->definedOnVictoryCheck) { lua_State *threadState = lua_newthread(this->mGlobalContext); lua_getglobal(threadState, "OnVictoryCheck"); if (!lua_isfunction(threadState, -1)) { // not found, mark and exit this->definedOnVictoryCheck = false; return TEAM_IND; } if (int errorcode = lua_resume(threadState, 0)) AvHLUA_OnError(lua_tostring(threadState, -1)); else { // Return the team that won if (lua_isnumber(threadState, -1)) return (AvHTeamNumber)((int)lua_tonumber(threadState, -1)); } } return TEAM_IND; }
static int auxresume(lua_State* L, lua_State* co, int narg) { int status = costatus(L, co); if (!lua_checkstack(co, narg)) luaL_error(L, "too many arguments to resume"); if (status != CO_SUS) { lua_pushfstring(L, "cannot resume %s coroutine", statnames[status]); return -1; /* error flag */ } lua_xmove(L, co, narg); lua_setlevel(L, co); status = lua_resume(co, narg); if (status == 0 || status == LUA_YIELD) { int nres = lua_gettop(co); if (!lua_checkstack(L, nres + 1)) luaL_error(L, "too many results to resume"); lua_xmove(co, L, nres); /* move yielded values */ return nres; } else { lua_xmove(co, L, 1); /* move error message */ return -1; /* error flag */ } }
void LuaEngineMgr::ResumeLuaThread(int ref) { CREATE_L_PTR; lua_State* expectedThread = NULL; lua_rawgeti(L, LUA_REGISTRYINDEX, ref); if(lua_isthread(L, -1)) expectedThread = lua_tothread(L, -1); if(expectedThread != NULL) { //push ourself on the stack lua_pushthread(expectedThread); //move the thread to the main lu state(and pop it off) lua_xmove(expectedThread, L, 1); if(lua_rawequal(L, -1, -2)) { lua_pop(L, 2); int res = lua_resume(expectedThread, lua_gettop(expectedThread)); if(res != LUA_YIELD && res) report(expectedThread); } else lua_pop(L, 2); luaL_unref(L, LUA_REGISTRYINDEX, ref); } }
static void timer_handler(void *data) { qltimer_t *timer; lua_State *state; timer = (qltimer_t*)data; state = timer->state; /* actor just sleep? */ if (qstring_empty(timer->mod)) { qdict_del_num(timer->actor->timers, timer->id); lua_resume(state, 0); return; } lua_getglobal(state, timer->mod); if (!lua_istable(state, -1)) { qerror("mod %s is not exist", timer->mod); qtimer_del(timer->engine, timer->id); return; } lua_getfield(state, -1, timer->func); if (!lua_isfunction(state, -1)) { qerror("%s.%s is not lua function", timer->mod, timer->func); qtimer_del(timer->engine, timer->id); return; } lua_pcall(state, 0, LUA_MULTRET, 0); }
void _draw(state_stack *stack) { state_desc *top = (state_desc*) table_ind(stack, stack->m_len-1); _talk_state *st = (_talk_state*) top->m_pData; int err; switch (st->m_iState) { case _STARTED: err = lua_resume(st->m_pThread, nullptr, 0); if (_util_lua_done(err, top)) { return; } _draw(stack); break; case _WAIT_CHOICE: font_print(g_font, 100, 100, "%s", st->m_sNPCText); menu_render(st->m_pChoices); break; case _WAIT_ANY: font_print(g_font, 100, 100, "%s", st->m_sNPCText); font_print(g_font, 100, 240, "Press a button for more exposition..."); break; case _STOPPED: top->m_isDead = true; break; } }
void lua_engine::resume(lua_State *L, int nparam, lua_State *root) { int s = lua_resume(L, NULL, nparam); switch(s) { case LUA_OK: if(!root) { std::map<lua_State *, std::pair<lua_State *, int> >::iterator i = thread_registry.find(L); if(i != thread_registry.end()) { luaL_unref(i->second.first, LUA_REGISTRYINDEX, i->second.second); thread_registry.erase(i); } } else lua_pop(root, 1); break; case LUA_YIELD: if(root) { int id = luaL_ref(root, LUA_REGISTRYINDEX); thread_registry[L] = std::pair<lua_State *, int>(root, id); } break; default: osd_printf_error("[LUA ERROR] %s\n", lua_tostring(L, -1)); lua_pop(L, 1); break; } }
void lua_player::resume_current_frame(int args) { std::cout << "resuming with " << args << " arguments" << std::endl; if(current_frame() != 0) { int r = lua_resume(current_frame(), args); if(r == LUA_YIELD) { } else if(r != 0) { std::string error = "Lua error: "; if(lua_gettop(current_frame ()) >= 1) { luabind::object error_msg(luabind::from_stack(current_frame (), -1)); if(luabind::type(error_msg) == LUA_TSTRING) error += luabind::object_cast<std::string>(error_msg); } ncl_window->error_occurred(error); } else { std::cout << "execution is finished" << std::endl; current_activation_frame ()->signal_execution_finished (); } } else { std::cout << "signal_all_execution_finished" << std::endl; Q_EMIT signal_all_execution_finished (); } std::cout << "resume_current_frame is finished" << std::endl; }
static int auxresume (lua_State *L, lua_State *co, int narg) { int status; if (!lua_checkstack(co, narg)) { lua_pushliteral(L, "too many arguments to resume"); return -1; /* error flag */ } if (lua_status(co) == LUA_OK && lua_gettop(co) == 0) { lua_pushliteral(L, "cannot resume dead coroutine"); return -1; /* error flag */ } lua_xmove(L, co, narg); status = lua_resume(co, L, narg); if (status == LUA_OK || status == LUA_YIELD) { int nres = lua_gettop(co); if (!lua_checkstack(L, nres + 1)) { lua_pop(co, nres); /* remove results anyway */ lua_pushliteral(L, "too many results to resume"); return -1; /* error flag */ } lua_xmove(co, L, nres); /* move yielded values */ return nres; } else { lua_xmove(co, L, 1); /* move error message */ return -1; /* error flag */ } }
static int ts_lua_http_intercept_run_coroutine(ts_lua_http_intercept_ctx * ictx) { int ret; const char *res; size_t res_len; lua_State *L; L = ictx->lua; ret = lua_resume(L, 0); switch (ret) { case 0: // finished res = lua_tolstring(L, -1, &res_len); ts_lua_http_intercept_setup_write(ictx); TSIOBufferWrite(ictx->output.buffer, res, res_len); TSVIONBytesSet(ictx->output.vio, res_len); break; case 1: // yield break; default: // error fprintf(stderr, "lua_resume failed: %s\n", lua_tostring(L, -1)); return -1; } return 0; }
void onTimerOut( void *arg ) { lua_State *L = (lua_State*) arg; /* push return value and the script can get it */ lua_pushnumber( L, 101 ); lua_resume( L, 1 ); }
void LuaThread(void *arg) { // Run Lua interpreter // Load the boot.lua file onto the stack as a chunk luaL_loadfile(L, "lua/bios.lua"); // Continuously resume the chunk until it finishes or errors int args = 0; while(LuaBox_Running) { int state = lua_resume(L, NULL, args); args = 0; if(state == LUA_OK) break; // Execution complete if(state != LUA_YIELD) { // Error of some kind printf("# Uncaught lua error (code %i)\nTraceback:", state); luaL_dostring(L, "print(debug.traceback())"); break; } // Handle yield below svcWaitSynchronization(LuaBox_EventMutex, U64_MAX); // Attempt to lock event list if(LuaBox_EventList == NULL) { // Release the event lock and wait for a signal svcReleaseMutex(LuaBox_EventMutex); svcWaitSynchronization(LuaBox_EventSignal, U64_MAX); // Wait for another thread to signal us an event svcClearEvent(LuaBox_EventSignal); // Clear the event svcWaitSynchronization(LuaBox_EventMutex, U64_MAX); // Attempt to lock event list } struct LuaBox_Event * ev = LuaBox_EventList; // Grab end of list if(ev != NULL) { switch(ev->type) { case LUABOX_EVENT_CHAR: lua_pushstring(L, "char"); // Push string 'char' onto stack char *charPressed = malloc(2); charPressed[0] = (char)ev->value; charPressed[1] = 0x0; lua_pushstring(L, charPressed); free(charPressed); args = 2; break; default: break; } struct LuaBox_Event * next = ev->next; free(ev); LuaBox_EventList = next; } // Release the event lock svcReleaseMutex(LuaBox_EventMutex); } // Execution complete past this point printf("# bios.lua execution complete\n"); while (1) { svcSleepThread(10000000ULL);} }
//lua_close(MainState); int CLuaThread::resume() { //fus::CLuaVM::stackDump( _vm); //return luabind::detail::resume_impl( getVM() , 0, 0); return lua_resume( _vm , 0); }
// // * RunState // // decides script to wait for user input, or finish // bool CQuestManager::RunState(QuestState & qs) { ClearError(); m_CurrentRunningState = &qs; int ret = lua_resume(qs.co, qs.args); if (ret == 0) { if (lua_gettop(qs.co) == 0) { // end of quest GotoEndState(qs); return false; } if (!strcmp(lua_tostring(qs.co, 1), "select")) { GotoSelectState(qs); return true; } if (!strcmp(lua_tostring(qs.co, 1), "wait")) { GotoPauseState(qs); return true; } if (!strcmp(lua_tostring(qs.co, 1), "input")) { GotoInputState(qs); return true; } if (!strcmp(lua_tostring(qs.co, 1), "confirm")) { GotoConfirmState(qs); return true; } if (!strcmp(lua_tostring(qs.co, 1), "select_item")) { GotoSelectItemState(qs); return true; } } else { sys_err("LUA_ERROR: %s", lua_tostring(qs.co, 1)); } WriteRunningStateToSyserr(); SetError(); GotoEndState(qs); return false; }
inline void luaResume(lua_State *L,int num) { int ret=lua_resume(L, num); if(!ret) { printf("закрываем L:%p\n",L); // lua_close(L); // L=0; // printf("закрываем L:%p\n",L); } }
int threading_run_ops(lua_State *L, int op_count, int *ops_left) { lua_sethook(L, &threading_yield_hook, lua_gethookmask(L) | LUA_MASKCOUNT, op_count); // The Lua hooking functionality uses this flag in what appears to be a // workaround for how luaV_execute functions. It normally sets the hookcount // to 1 so that luaV_execute will immediately reenter the hook logic. // It seems to use this to reset the hookcount. However, it would not make // sense to call the user hook function again, as the interpreter would have // run for 0 ticks. Lua therefore uses this flag in what appears to be a // workaround so that the user hook won't be called that first time. However, // when we call lua_sethook, it already resets hookcount. If this flag is // not cleared, the interpreter will actually run 2x the number of opcodes. // So as an apparent hack on top of a hack, we clear this flag here. L->ci->callstatus &= ~CIST_HOOKYIELD; int old_tos = lua_gettop(L); // Subtract 1 to ignore the argument to lua_resume if first run // TODO(rqou): This is really hacky. From reading the comments in ldo.c, it // appears that this works unless there is an error (resuming a coroutine // that is already running). if (L->status == LUA_OK) { old_tos--; } int status = lua_resume(L, 0, 0); int new_tos = lua_gettop(L); if (ops_left) { int left = L->hookcount; // TODO(rqou): For reasons that I don't understand, luaG_traceexec sets // hookcount back to 1 when it is 0. We set it back to 0 here. This has a // side-effect where any thread that yields to block with exactly 1 opcode // left will "lose" this one cycle. It probably doesn't matter though. if (left == 1) left = 0; *ops_left = left; } if (status == LUA_OK) { return THREADING_EXITED; } else if (status == LUA_YIELD) { // It is impossible to return data from lua_yield with in a hook for some // reason (luaD_hook calls restorestack). Therefore, we assume we are // preempted if we have no information pushed. Otherwise, if we are // yielding due to blocking on something, the call to yield must have // pushed an int indicating why it yielded. if (old_tos == new_tos) { return THREADING_PREEMPT; } else { int ret = lua_tointeger(L, -1); lua_pop(L, 1); return ret; } } else { return THREADING_ERROR; } }
void noteye_uiresume() { if(!uithread) { noteyeError(11, "no UI thread to resume", NULL); return; } int status = lua_resume(uithread, 0); if(status != LUA_YIELD) { noteyeError(12, "uifinish did not finish thread", lua_tostring(uithread, -1)); uithread_err = true; } }
void Script :: logic(float t) { const unsigned int time_between_ticks = round_int(1000.0f / m_TickFrames); // accumualate time m_TickTime.logic(t); //std::cout << m_TickTime.milliseconds() << std::endl; if(m_TickTime.milliseconds() < time_between_ticks) { return; } unsigned int remaining_frames = (unsigned int)(m_TickTime.milliseconds() / time_between_ticks - 1); unsigned int remaining_time = (unsigned int)m_TickTime.milliseconds() % time_between_ticks; // DEBUG{ //Log::get().write(str("Remaining Frames: ") + str(remaining_frames)); //assert(remaining_frames < 5); // }DEBUG m_TickTime.reset(); m_TickTime.logic(((remaining_frames)*time_between_ticks) + remaining_time); // need to sleep? if(m_SleepFrames > 0) { // sleep this frame m_SleepFrames -= 1; return; } int status = lua_resume(m_pThread, 0); if(status != LUA_YIELD) { // either error or done with script if(status == LUA_ERRRUN && lua_isstring(m_pThread, -1)) { Log::get().error(str(lua_tostring(m_pThread, -1))); return; // bail } else { // script is finished m_bDone = true; } } // figure out how many frames to sleep before resuming script if(lua_isnumber(m_pThread, 1)) { m_SleepFrames = round_int(lua_tonumber(m_pThread, 1) - 1.0); if(m_SleepFrames < 0) m_SleepFrames = 0; } }
void noteye_uifinish() { if(!uithread) { noteyeError(13, "no UI thread to finish", NULL); return; } int status = lua_resume(uithread, 0); if(status != 0) { noteyeError(14, "uiresume did not yield", lua_tostring(uithread, -1)); return; } uithread = NULL; }
int main() { lua_State *L = luaL_newstate(); luaL_openlibs(L); luaL_loadfile(L, "test.lua"); while (1) { lua_pushfstring(L, "%d", lua_gettop(L)); lua_resume(L, NULL, 1); printf("back\n"); } lua_close(L); }
int LuaTimeout::SafeResume(lua_State* coroutine) { luaVM = coroutine; call_id++; active = true; int resume_result = lua_resume(coroutine, 0); active = false; if(luaL_getbailout(luaVM)) { lua_pop(luaVM, lua_gettop(luaVM)); //Stack may well be trashed, so clear it lua_pushstring(coroutine, abort_message.c_str()); return LUA_ERRRUN; } if(resume_result != LUA_YIELD && resume_result != 0) { Logger::ErrorOut() << "Lua Error: Begin stack dump\n"; //Stack is not unwound, so can dump it /* Stack dump lifted wholesale from http://www.lua.org/pil/24.2.3.html */ int i; int top = lua_gettop(coroutine); for (i = 1; i <= top; i++) { /* repeat for each level */ int t = lua_type(coroutine, i); switch (t) { case LUA_TSTRING: /* strings */ Logger::ErrorOut() << i << " String: " << lua_tostring(coroutine, i); break; case LUA_TBOOLEAN: /* booleans */ Logger::ErrorOut() << i << " Boolean: " << (lua_toboolean(coroutine, i) ? "true" : "false"); break; case LUA_TNUMBER: /* numbers */ Logger::ErrorOut() << i << " Number: " << lua_tonumber(coroutine, i); break; default: /* other values */ Logger::ErrorOut() << i << " Other: " << lua_typename(coroutine, t); break; } Logger::ErrorOut() << "\n"; } Logger::ErrorOut() << "\n End stack dump\n"; /* end the listing */ //Now tidy up stack. Error message should be left at the top, but everything else cleared away lua_insert(coroutine, 1); lua_pop(coroutine, lua_gettop(coroutine) - 1); } return resume_result; }
std::string LuaCoroutine::Resume() { PushToStack(state.get()); lua_State* thread = lua_tothread(state.get(), -1); lua_pop(state.get(), 1); int status = lua_resume(thread, NULL, lua_gettop(thread)); if (status != LUA_OK && status != LUA_YIELD) { return LuaGetLastError(thread); } return "No errors"; }