lua-users home
lua-l archive

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

Hi folks,

I'm wondering if there's a better way of doing this:

in a C userdata object, I want to call some Lua funcion with the same C userdata as parameter. AFAIK, for this to work I need a reference to the userdata, which I create when the userdata is created and then keep in the userdata itself. Because this is a cyclic reference, I must create an extra weak-valued registry to keep all those references in.

Is there a better way? In other words, can I push the userdata on the stack given only the pointer to that userdata? That would be nnnnnice.

Extended example (broken code, this is meant as an illustration):

-------- Definition -----------
struct NuggetHandle
int m_SelfRef; // Reference to self userdata. This is stored in the weak self-ref registry in m_Lib, NOT in LUA_REGISTRYINDEX! This makes sure the ref is removed
// moar data

-------- Creation of the object --------
    // Create new Lua Nugget object.
    NuggetHandle* newNugget = (NuggetHandle*)lua_newuserdata(L, someSize);
    luaL_getmetatable(L, NUGGET_LUA_TYPENAME);
    lua_setmetatable(L, -2);

    // Set self ref into weak registry
lua_rawgeti(L, LUA_REGISTRYINDEX, nclass->m_Lib->m_SelfRefRegistry); // get self ref reg
    lua_pushvalue(L, -2);
newNugget->m_SelfRef = luaL_ref(L, -2); // store into self ref registry
    lua_pop(L, 1);  // pop self ref registry

-------- Calling a callback ---------------
void NuggetHandle::passOnCallback(lua_State* L)
// note that we only have the userdata pointer here, for example we got
// called from a system-defined UI callback
lua_pushSomeFunction(L); // push some Lua callback function on the stack we want to call

// Push self onto Lua stack: ouch! get the weak registry, get the reference, pop weak registry
    lua_rawgeti(L, LUA_REGISTRYINDEX, m_Class->m_Lib->m_SelfRefRegistry);
    lua_rawgeti(L, -1, m_SelfRef);
    lua_remove(L, -2);

    lua_pushstring(L, "yay more params");
lua_call(L, 2, 0); // first param: reference to self userdata