lua多线程

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。网上教程很多。

猜你喜欢

转载自blog.csdn.net/zgl390963305/article/details/79948795
今日推荐