Interfacing C and Lua


#1

This subject is best treated by Lua books such as Programming in Lua, but I’ll give a quick overview anyway, to answer some frequent questions.

Communication between C and high level languages is generally complex, in a large part because C lets its users handle memory manually, whereas modern languages automate this task with a garbage collector. Lua is significantly simpler to interface than most other languages: it uses a pseudo-stack API, i.e. you can push and pop C values on a Lua/C communication stack, and use some operators that let you command Lua from C. For instance, if you want to store a C string into a Lua global var, you’ll probably write something like this:

static int some_c_function_to_export_in_lua( lua_State *L);

int luaopen_mystuff( lua_State *L) {
  char *my_c_string = ... ;                               // your C string
  lua_pushstring(   L, my_c_string);                      // push string on top of stack
  lua_setglobal(    L, "LUA_GLOBAL_VAR_NAME");            // store it in global var
  lua_pushfunction( L, some_c_function_to_export_in_lua); // push the function on the stack
  lua_setglobal(    L, "MY_C_FUNCTION");                  // store it in a global var
  return 0;                                               // this function returns 0 Lua results
}

This function takes a lua_State*, and returns an int, it’s therefore callable from Lua. The standard way to call it at init time, so that the global variable is accessible as soon as the Lua VM starts, it to put it in the initializers table which is passed to luaW_start(). Check some of the samples provided in the distribution.

static const luaL_Reg initializers[] = {
   ...
   { "mystuff", luaopen_mystuff },
   ...
   { NULL, NULL } };

adl_main() {
   ...
   luaW_start( initializers);
   ...
}

Look at the Lua reference manual: you’ll find lua_pushxxx() functions to push stuff in the stack, lua_checkxxx() to get stuff from the stack, plus many functions to manipulate global variables, tables, function calls etc.

A design hint to accelerate your developements: write the simplest possible C function, then write a wrapper function in Lua that takes in charge other aspects (gentler API, arguments consistency, synchronization etc). You’ll only translate this back in C if it’s required by performances, but most of the time you’ll find out that it isn’t necessary.

Finally, there are several tools which generate wrapper code around C functions to export them in Lua automatically. However, after you’ll have written a couple of them by hand, you’ll probably find it fast and easy enough not to require such tools.