|
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 |