2

I am making my own game engine, using Lua C API. I got such Lua table hierarchy:

my_lib = {
  system = { ... },
  keyboard = { ... },
  graphics = { ... },
  ...
}

Also I got some C function, I want to register, something like that:

inline static int lua_mylib_do_cool_things(lua_State *L) {
    mylib_do_cool_things(luaL_checknumber(L, 1));
    return 0;
}

So, how can I register it like member of my_lib sub-table, just like that?

my_lib = {
  system = { do_cool_things, ... },
  keyboard = { ... }
  graphics = { ...}
}

Now I only know the way to register members of global tables, it works like that:

inline void mylib_registerFuncAsTMem(const char *table, lua_CFunction func, const char *index) {
    lua_getglobal(mylib_luaState, table);
    lua_pushstring(mylib_luaState, index);
    lua_pushcfunction(mylib_luaState, func);
    lua_rawset(mylib_luaState, -3);
}

But what about sub-tables?

  • There are [API functions](https://www.lua.org/manual/5.3/manual.html#luaL_setfuncs) that can help with registering functions into tables, which version of Lua are you using? – Adam Apr 13 '16 at 17:29
  • Thanks for respond. I am using Lua 5.1, and it looks like there is no such API function there. – Vasiliy Pupkin Apr 13 '16 at 18:02
  • True, this function was added in Lua 5.2, but you might be able to use [luaL_register](https://www.lua.org/manual/5.1/manual.html#luaL_register) instead. – Adam Apr 13 '16 at 18:05
  • @VasiliyPupkin Of course there are – Cubic Apr 13 '16 at 18:05
  • Could you kindly write some example code? As I said, I know how to work with global tables, but not sub-ones. – Vasiliy Pupkin Apr 13 '16 at 18:14
  • `rawget` a subtable, instead of first `getglobal`. Rest is exactly the same. – Oleg V. Volkov Apr 13 '16 at 18:44

1 Answers1

4

A simple way to register multiple Lua C function into a table (using Lua 5.1) is to use luaL_register.

First, implement your Lua functions, they should take the form of a lua_CFunction.

static int graphics_draw(lua_State *L) {
    return luaL_error(L, "graphics.draw unimplemented");
}

static int system_wait(lua_State *L) {
    return luaL_error(L, "system.wait unimplemented");
}

Next, create a luaL_Reg structure for each sub-table with your Lua functions and their names (keys).

static const struct luaL_Reg module_graphics[] = {
    {"draw", graphics_draw},        
    // add more graphic functions here.. 
    {NULL, NULL}  // terminate the list with sentinel value
};

static const struct luaL_Reg module_system[] = {
    {"wait", system_wait},        
    {NULL, NULL}
};

Then, in the function where you return your module table create each sub-table and register its functions.

int luaopen_game(lua_State *L) {    
    lua_newtable(L);  // create the module table

    lua_newtable(L);                          // create the graphics table
    luaL_register(L, NULL, module_graphics);  // register functions into graphics table
    lua_setfield(L, -2, "graphics");          // add graphics table to module

    lua_newtable(L);                          // create the system table
    luaL_register(L, NULL, module_system);    // register functions into system table
    lua_setfield(L, -2, "system");            // add system table to module

    // repeat the same process for other sub-tables

    return 1;  // return module table
}

This should result in a module table with the following structure:

game = {
    graphics = {
        draw -- C function graphics_draw
    },
    system = {
        wait -- C function system_wait
    }
}
Adam
  • 3,053
  • 2
  • 26
  • 29
  • Thank you very much. After I asked the question, I found the solution myself, but yours is much more complex. – Vasiliy Pupkin Apr 13 '16 at 19:43
  • 1
    You're welcome. This pattern is typically used for Lua modules written in C, as shown in the excellent [Programming in Lua](http://www.lua.org/pil/28.1.html) book. The first edition is available online for free. – Adam Apr 13 '16 at 19:48