Home Contact Me Tutorials

Reading A Lua Configuration File From C

Contents

Introduction

Lua is a scripting language that is embeddable in C/C++ programs. With Lua's C API, you can use a Lua file to configure your program settings.

Take for example the following Lua file that could serve as the configuration for a computer game. It specifies the screen resolution and the locations of images.

settings = {
  resolution = {
    width = 800,
    height = 600,
    fullscreen = true
  },
  images = {
    "C:\\apple.bmp",
    "C:\\banana.bmp",
    "C:\\carrot.bmp"
  }
}

It's easy to access the data from Lua:
print( settings.resolution.width )       -- prints 800
print( settings.resolution.fullscreen )  -- prints true
print( settings.images[ 1 ] )            -- prints C:\apple.bmp

It takes a bit more work to access the same data from a C program. Although Lua's C API provides a lua_getglobal function for accessing global variables, there are no functions for easily accessing nested variables.

In this tutorial I will describe a few C functions that I created to accomplish this. They can be downloaded at the end of the tutorial. The functions have been tested with version 5.1 of Lua.

Using The Functions

The following table lists the functions I've written.

Function Description
lua_stringexpr Evaluates a Lua expression that returns a string.
lua_numberexpr Evaluates a Lua expression that returns a number.
lua_intexpr Evaluates a Lua expression that returns an integer.
lua_boolexpr Evaluates a Lua expression that returns a bool.

The print_settings function below shows how to use the functions. Assume that the lua_State that is passed into print_settings has been initialized with the Lua settings above using luaL_dofile.

void print_settings( lua_State* L ) {
  const char* width = 0 ;
  int height = -1 ;
  int fullscreen = -1 ;
  int image_count = -1 ;
  int i = 0 ;

  /* Read resolution settings */
  width = lua_stringexpr( L, "settings.resolution.width", 0 );
  lua_intexpr( L, "settings.resolution.height", &height ) ;
  fullscreen = lua_boolexpr( L, "settings.resolution.fullscreen" );

  /* Print resolution settings */
  printf( "settings.resolution.width = %s\n", width );
  printf( "settings.resolution.height = %d\n", height );
  printf( "settings.resolution.fullscreen = %s\n",fullscreen ? "true":"false" );

  /* Read the number of images */
  lua_intexpr( L, "#settings.images", &image_count ) ;

  /* Print the image file paths. */
  for ( i=0; i<image_count; ++i ) {
    const char* image ;
    char expr[64] = "" ;
    sprintf( expr, "settings.images[%d]", i+1 );
    image = lua_stringexpr( L, expr, 0 );
    printf( "settings.images[%d] = %s\n", i, image );
  }
}

Here's the output after calling print_settings:

settings.resolution.width = 800
settings.resolution.height = 600
settings.resolution.fullscreen = true
settings.images[1] = C:\apple.bmp
settings.images[2] = C:\banana.bmp
settings.images[3] = C:\carrot.bmp

How It Works

The C functions work by assigning a given Lua expression to a global Lua variable. For example, if the expression is settings.resolution.width, the following is added into the Lua state:

evalExpr = settings.resolution.width

The global variable evalExpr is then accessed from C using lua_getglobal.

The following is the source code for the lua_stringexpr function. All of the other functions are similarly defined.

/**
  Evaluates a Lua expression and returns the string result.
  If an error occurs or the result is not string, def is returned.
*/
const char* lua_stringexpr( lua_State* L, const char* expr,
                            const char* def ) {
  const char* r = def ;
  char buf[256] = "" ;
  /* Assign the Lua expression to a Lua global variable. */
  sprintf( buf, "evalExpr=%s", expr );
  if ( !luaL_dostring( L, buf ) ) {
    /* Get the value of the global varibable */
    lua_getglobal( L, "evalExpr" );
    if ( lua_isstring( L, -1 ) ) {
      r = lua_tostring( L, -1 );
    }
    /* remove lua_getglobal value */
    lua_pop( L, 1 );
  }
  return r ;
}

Downloads


File Description
lua-config-file.zip The functions are defined in luautils.h and luautils.c. A sample program (main.c) and a Code::Blocks project are included.