lua5.3.4在Windows下多线程
作者:Mrzhu007
日期:2018-04-15
博客地址:金色世界
简介
之前做的一个测试项目。在使用lua脚本对一些固件测试的时候,需要lua满足多线程。来进行同步检测
实现
该方案由网友提供,在github上也可以下载。在使用过程中,有一些bug已进行修改。适配与lua5.3.4版本.
以防以后忘掉,故整理成文档。各位网友喜欢的话不妨拿去使用。我只在测试项目中使用。
在使用多线程的时候请让线程自己终止,或者使用lua变量外界控制。
不要使用库中提供的终止线程函数。有问题,但不影响使用,就没改。
- 第一步GitHub下载最新lua源码
第二步添加一下.c文件名字自己取建议systhread。将下面的源码复制进去
#include <Windows.h> #include "lua.h" #include "lauxlib.h" #include "lualib.h" #include "lstate.h" #define TNAMESTR_SYSTHREAD "g_utype_systhread"// userdata type name typedef struct _SysThread { lua_State *thread; int ref;//在C注册表中的引用,防止被回收 DWORD id; HANDLE handle; }SysThread; DWORD WINAPI ThreadProc(LPVOID lp) { SysThread *st = (SysThread *)lp; int ntop = lua_gettop(st->thread); int err = lua_pcall(st->thread, ntop-1, 0, 0); if (err) printf("[Thread %x callback error] %s", st, lua_tostring(st->thread, -1)); if (st->ref) luaL_unref(st->thread, LUA_REGISTRYINDEX, st->ref); return err; } static int luaB_newthread (lua_State *L); static int luaB_resumethread (lua_State *L) { SysThread *st = (SysThread *)luaL_checkudata(L, 1, TNAMESTR_SYSTHREAD); int count = ResumeThread(st->handle); if (count == -1) lua_pushboolean(L, 0); else lua_pushinteger(L, count); return 1; } static int luaB_suspendthread (lua_State *L) { SysThread *st = (SysThread *)luaL_checkudata(L, 1, TNAMESTR_SYSTHREAD); int count = SuspendThread(st->handle); if (count == -1) lua_pushboolean(L, 0); else lua_pushinteger(L, count); return 1; } static int luaB_terminatethread(lua_State *L) { SysThread *st = (SysThread *)luaL_checkudata(L, 1, TNAMESTR_SYSTHREAD); BOOL b = TerminateThread(st->handle, lua_isnoneornil(L, 2) ? 0 : luaL_checkinteger(L, 2)); lua_pushboolean(L, b); luaL_unref(st->thread, LUA_REGISTRYINDEX, st->ref); st->ref = 0; return 1; } static int luaB_waitthread(lua_State *L) { SysThread *st = (SysThread *)luaL_checkudata(L, 1, TNAMESTR_SYSTHREAD); WaitForSingleObject(st->handle, lua_isnoneornil(L, 2) ? INFINITE : luaL_checkinteger(L, 2)); return 0; } static int luaB_getthreadexitcode(lua_State *L) { SysThread *st = (SysThread *)luaL_checkudata(L, 1, TNAMESTR_SYSTHREAD); DWORD exitCode; BOOL b = GetExitCodeThread(st->handle, &exitCode); if (b) lua_pushinteger(L, exitCode); else if (exitCode == STILL_ACTIVE) lua_pushboolean(L, b); else lua_pushnil(L); return 1; } static int luaB_getid(lua_State *L) { SysThread *st = (SysThread *)luaL_checkudata(L, 1, TNAMESTR_SYSTHREAD); lua_pushinteger(L, st->id); lua_pushinteger(L, (int)st->handle); return 2; } static int luaB_threadsleep(lua_State *L) { Sleep(luaL_checkinteger(L, 1)); return 0; } static const luaL_Reg systhreadlib[] = { {"create",luaB_newthread}, {"resume",luaB_resumethread}, {"suspend",luaB_suspendthread}, {"terminate",luaB_terminatethread}, {"wait",luaB_waitthread}, {"exitcode",luaB_getthreadexitcode}, {"getid",luaB_getid}, {"sleep",luaB_threadsleep}, {NULL,NULL} }; static int luaB_newthread (lua_State *L) { int nTop; lua_State* newthr; int ref; SysThread *st; luaL_checktype(L, 1, LUA_TFUNCTION); nTop = lua_gettop(L); newthr = lua_newthread(L); ref = luaL_ref(L, LUA_REGISTRYINDEX);//放到C注册表中防止被回收 lua_xmove(L, newthr, nTop);//把启动函数以及参数移到新的lua_State 中 st = (SysThread *)lua_newuserdata(L, sizeof(SysThread)); st->ref = ref; st->thread = newthr; //创建系统线程 if ((st->handle = CreateThread(NULL, 0, ThreadProc, st, CREATE_SUSPENDED, &st->id))) { luaL_newmetatable(L, TNAMESTR_SYSTHREAD); //创建一个类型为 TNAMESTR_SYSTHREAD 的userdata luaL_newlib(L,systhreadlib); // lua_setfield(L, -2, "__index"); lua_setmetatable(L, -2); } else //创建失败,返回false if (!st->handle) { lua_pushboolean(L, 0); } return 1; } int luaopen_systhread(lua_State *L) { luaL_newlib(L, systhreadlib); return 1; }
第三步在linit.c文件中的loadedlibs结构中添加如下:
{LUA_SYSTHREADLIBNAME, luaopen_systhread},
第四步在lstate.h文件中在添加
//在lua_newstate中TString *strcache[STRCACHE_N][STRCACHE_M]; /* cache for strings in API */后面添加 CRITICAL_SECTION cri_sec;
第五步在lstate.c文件中添加
//在lua_newstate中g->gcstepmul = LUAI_GCMUL;后面 InitializeCriticalSection(&g->cri_sec);
第六步在lualib.h文件中添加
#define LUA_SYSTHREADLIBNAME "systhread" LUAMOD_API int (luaopen_systhread) (lua_State *L);
第七步在lundump.c文件中LoadString函数前面添加
#undef LoadString //ADDED BY ZHUGAOLEI
最后
好了,到此为止可以开启自己的lua多线程之路了。至于怎么编译lua和怎么使用lua。网上教程很多。