Search code examples
cstructlualua-api

Storing a C structure in the Lua registry


As I'm integrating Lua into my C program, I've been using a static pointer to a C struct to store an object I need to reuse in methods that I bind to the Lua state.

However, this does not work once I split my Lua lib from the main program, so it seems I need to use the registry to store my struct.

How do I go about storing my C struct pointer in the Lua registry?

This is what I'm currently doing:

static augeas *aug = NULL;


static int lua_aug_get(lua_State *L) {
    // Use aug to do something here
    /* return the number of results */
    return 1;
}

struct lua_State *luaopen_augeas(augeas *a) {
    lua_State *L = luaL_newstate();
    aug = a; // this clearly does not work
    luaL_openlibs(L);
    // The methods below will need to access the augeas * struct
    // so I need to push it to the registry (I guess)
    static const luaL_Reg augfuncs[] = {
        { "get", lua_aug_get },
        { "label", lua_aug_label },
        { "set", lua_aug_set },
        { NULL, NULL }
    };

    luaL_newlib(L, augfuncs);
    lua_setglobal(L, "aug");

    return L;
}

Edit: from an answer I got on IRC, it seems I should be using a metatable, so I'm currently looking into this.


Solution

  • If registry is not safe-enough place to store a pointer, you can push it as an upvalue to specific functions:

    static int lua_aug_get(lua_State *L) {
      augeas *aug = lua_touserdata(L, lua_upvalueindex(1));
      // Do stuff with aug
      return 1;
    }
    
    static const luaL_Reg augfuncs[] = {
        { "get", lua_aug_get },
        { "label", lua_aug_label },
        { "set", lua_aug_set },
        { NULL, NULL }
    };
    lua_createtable(L, 0, 0);
    for (size_t i = 0; augfuncs[i].name; i++) {
        lua_pushlightuserdata(L, a);
        lua_pushcclosure(L, augfuncs[i].func, 1);
        lua_setfield(L, -2, augfuncs[i].name);
    }
    

    But it is okay to store it in registry. It is not script-accessible, except for debug library, usually not exposed in sandboxes. And if other libraries create selfish mess there, you're in trouble anyway.