lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


 

I am writing an application that hosts a small lua scripting environment. In my application, I want to load a script and then create a number of lua threads that will each have their own environment. Then my application can iterate over the list of threads and call each thread’s co-routine until all co-routines have completed. Each co-routine has its own “global” variable that will be unique. I have attached a trivial C file that duplicates the core functionality.

 

My issue is that the globals I declare in C and push to the thread stack are always nil when used in the lua script, but have the correct value when I retrieve them from C methods. Can someone tell me what I am doing wrong?

 

The only solution I have found is to reload the script in each thread – change #if 0 to #if 1. However, in my main application, I could be creating 10,000 or more lua threads. Re-loading the script in each thread is not ideal in this case.

 

I suspect that the method I invoke is using the global environment of the main thread instead of my sub-thread’s global environment. How would I change that behavior?

 

Marcus

 

 

-- main.c

 

#include "stdio.h"

#include "assert.h"

#include <lua.h>

#include <lauxlib.h>

#include <lualib.h>

 

int l_TestRoutine(lua_State *L)

{

    //When I get the global variable id from the stack

    //I get the correct value

    lua_getglobal(L, "id");

    luaL_checktype(L, -1, LUA_TNUMBER);

    printf("Id: %d\n", (int)lua_tointeger(L, -1));

 

    lua_pop(L, 1); // remove the id

    return lua_yield(L, 0);

 

}

 

int main(int argc, char ** argv)

{

    lua_State*  LThreads[10];

 

    /* initialize lua */

    lua_State *L = lua_open();

    luaL_openlibs(L);

 

    int error = luaL_loadfile(L, "foo.lua");

    printf("Error code: %d\n", error);

    if (error != 0)

    {

        printf("Error: %s\n",lua_tostring(L,-1));

        lua_pop(L, 1);

    }

 

    error = lua_pcall(L, 0, LUA_MULTRET, 0);

    printf("Error code: %d\n", error);

 

    if (error != 0)

    {

        printf("Error: %s\n",lua_tostring(L,-1));

        lua_pop(L, 1);

    }

 

    lua_register(L, "Test", l_TestRoutine);

    lua_pushinteger(L, 9999);

    lua_setglobal(L, "id");

 

    //now create many lua threads, each with it's own global variable

    //and try to access the global

 

    int i;

    for (i = 0; i < 10; ++i)

    {

        LThreads[i] = lua_newthread(L);

 

        //create our own copy of the globals table

        lua_newtable( LThreads[i] ); //new globals table

        lua_newtable( LThreads[i] ); //metatable

        lua_pushliteral( LThreads[i], "__index" );

        lua_pushvalue( LThreads[i], LUA_GLOBALSINDEX ); //original globals

        lua_settable( LThreads[i], -3 );

        lua_setmetatable( LThreads[i], -2 );

        lua_replace( LThreads[i], LUA_GLOBALSINDEX ); //replace new globals

 

#if 0

        error = luaL_loadfile(LThreads[i], "foo.lua");

        printf("Error code: %d\n", error);

        if (error != 0)

        {

            printf("Error: %s\n",lua_tostring(L,-1));

            lua_pop(LThreads[i], 1);

        }

        error = lua_pcall(LThreads[i], 0, LUA_MULTRET, 0);

        printf("Error code: %d\n", error);

#endif

 

        lua_pushinteger(LThreads[i], i);

        lua_setglobal(LThreads[i], "id");

 

        //setup to call main for the first time

        lua_getglobal(LThreads[i], "Main");

    }

 

    int j;

    for (i = 0; i < 100; ++i)

    {

        for (j= 0; j < 10; ++j)

        {

            error = lua_resume(LThreads[j], 0);

 

            if ((error != LUA_YIELD)

                && (error != 0))

            {

                printf("Error: %s\n",lua_tostring(LThreads[i], -1));

                lua_pop(LThreads[i], 1);

 

                //What should I do to handle an error?

                assert(0);

            }

        }

    }

 

    /* teardown */

    lua_close(L);

 

    return 0;

}

 

--  Lua script

function Mine ()

    print("called Mine")

end

 

function Main()

    while true do

        print (id)

        Test()

    end

end