使用 Windows 纤程实现非阻塞 Lua 执行 |
|
以下示例是一个控制台应用程序,它运行一个 Lua 脚本,但可以通过按任意键随时停止。脚本可以执行任何操作,程序仍然可以处理按键。
Main.cpp
#ifndef _WIN32_WINNT #define _WIN32_WINNT 0x0400 // Necessary to enable fiber functions. #endif #include <Windows.h> #include <conio.h> extern "C" { #include "lua.h" #include "lualib.h" #include "lauxlib.h" } LPVOID g_PrimaryFiber = NULL; LPVOID g_LuaFiber = NULL; lua_State* pLua = NULL; VOID CALLBACK LuaFiberProc(PVOID lpParameter) { luaL_dofile(pLua, "Script.lua"); } int main() { pLua = luaL_newstate(); luaL_openlibs(pLua); g_PrimaryFiber = ConvertThreadToFiber(NULL); g_LuaFiber = CreateFiber(0, LuaFiberProc, NULL); for (;;) { if (_kbhit()) { printf("This program has successfully used fibers!\n"); printf("Goodbye.\n"); return 0; } SwitchToFiber(g_LuaFiber); } }
以下是 lvm.c 中显示的更改部分
... //////////////// // CHANGES HERE //////////////// #ifndef _WIN32_WINNT #define _WIN32_WINNT 0x0400 #endif #include <Windows.h> extern LPVOID g_PrimaryFiber; //////////////// //////////////// void luaV_execute (lua_State *L, int nexeccalls) { LClosure *cl; StkId base; TValue *k; const Instruction *pc; reentry: /* entry point */ lua_assert(isLua(L->ci)); pc = L->savedpc; cl = &clvalue(L->ci->func)->l; base = L->base; k = cl->p->k; /* main loop of interpreter */ for (;;) { //////////////// // CHANGES HERE //////////////// Instruction i; StkId ra; SwitchToFiber(g_PrimaryFiber); i = *pc++; //////////////// //////////////// if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) && (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) { ...
它的工作原理是在两个纤程中运行程序:主纤程和 Lua 纤程。主纤程是程序的主要部分,Lua 纤程是 Lua 脚本运行的地方。luaV_execute 被修改为在脚本操作之间切换回主纤程,主纤程在完成处理后切换回 Lua 纤程。
已知问题