Valkea
Valkea

Reputation: 1226

Is it possible to expose (from C++) the "same" constant with different values to multiple Lua coroutines?

I am writing a library called LuaVM to manage the interaction between Lua Scripts and my own project using the Lua library.

I am searching a way to expose somewhat "local" coroutine variables. So I can access different values from different coroutines using the same "variable name". But as you probably know coroutines share the same global environment with their lua_State parent and all they other coroutines issued from the same lua_State.

For example I would like to expose the thisItem global to each coroutine so each script (each one with it's own coroutine) could call thisItem and get a different value, even if they are using the same lua_State parent and are nested.

So I tried different approach, such as exposing / unexposing the value using a stack, but none was "thread" proof indeed.

My last attempt was to associate the global thisItem with a metatable where __index and/or __call keys were modified to call a function which in turn tried to return the right value.

Here is how I expose it

//-- Define a callback function
int LuaVM::DEBUGFUNCTION(lua_State *L)
{
    //-- Do stuff to return the right value
    return 1;
}

//-- Create callback metatable in the constructor
LuaVM::LuaVM()
{
    //--Init Lua
    mState = luaL_newstate();
    luaL_openlibs(mState);
    /* etc...*/

    //-- Define the callback metatable
    luaL_newmetatable(mState, "ThreadLocalMT");
    lua_pushstring(mState, "__call");
    lua_pushcclosure(mState, DEBUGFUNCTION,0);
    lua_settable(mState, -3);
}

//-- Then define the exposeInstance function
template <class C>
bool LuaVM::exposeInstance(C* _ptr, /*other stuff*/ )
{
    LuaObject<C>* ret = (LuaObject<C>*)lua_newuserdata(mState, sizeof(LuaObject<C>));
    ret->ptr = _ptr;

    luaL_getmetatable(mState, "ThreadLocalMT");
    lua_setmetatable(mState, -2);
    lua_setglobal(mState,"thisItem");

    /* other stuff */
    return true;
}

But it's not really what I was looking for... (I need to call thisItem() instead of the variable thisItem) and I'm wondering if there is a way to create a table to store all the values and return the right one using a less "tricky" solution.

I am not accustomed with threads nor with Lua C-api and so I need your help. There is maybe a better way to manage this problem in a multi-thread environment ?

Thank you

Upvotes: 0

Views: 329

Answers (1)

Doug Currie
Doug Currie

Reputation: 41180

If you are using Lua 5.1.x, then you can use lua_setfenv to set the environment of the coroutine (as described here). Use a table with the global bindings you want, and optionally with a metatable with an __index of the usual globals _G. This mechanism is described in the Lua 5.1 reference manual section 2.9 Environments

Things are a bit more complicated (for this use-case) in Lua 5.2; the relevant reference manual section is 2.2 – Environments and the Global Environment

Upvotes: 1

Related Questions