This first edition was written for Lua 5.0. While still largely relevant for later versions, there are some differences.
The fourth edition targets Lua 5.3 and is available at Amazon and other bookstores.
By buying the book, you also help to support the Lua project.
Programming in Lua | ||
Part IV. The C API Chapter 25. Extending your Application |
An important use of Lua is as a configuration language. In this chapter, we will illustrate how we can use Lua to configure a program, starting with a simple example and evolving it to perform more complex tasks.
As our first task,
let us imagine a simple configuration scenario:
Your C program (let us call it pp
) has a window
and you want the user to be able to specify the
initial window size.
Clearly, for such simple tasks,
there are several options simpler than using Lua,
such as environment variables or files with name-value pairs.
But even using a simple text file,
you have to parse it somehow;
so, you decide to use a Lua configuration file
(that is, a plain text file that happens to be a Lua program).
In its simplest form,
this file can contain something like the next lines:
-- configuration file for program `pp' -- define window size width = 200 height = 300
Now, you must use the Lua API to direct Lua to parse this file,
and then to get the values of the global variables width
and height
.
The following function does the job:
#include <lua.h> #include <lauxlib.h> #include <lualib.h> void load (char *filename, int *width, int *height) { lua_State *L = lua_open(); luaopen_base(L); luaopen_io(L); luaopen_string(L); luaopen_math(L); if (luaL_loadfile(L, filename) || lua_pcall(L, 0, 0, 0)) error(L, "cannot run configuration file: %s", lua_tostring(L, -1)); lua_getglobal(L, "width"); lua_getglobal(L, "height"); if (!lua_isnumber(L, -2)) error(L, "`width' should be a number\n"); if (!lua_isnumber(L, -1)) error(L, "`height' should be a number\n"); *width = (int)lua_tonumber(L, -2); *height = (int)lua_tonumber(L, -1); lua_close(L); }First, it opens the Lua package and loads the standard libraries (they are optional, but usually it is a good idea to have them around). Then, it uses
luaL_loadfile
to load the chunk from file filename
and calls lua_pcall
to run it.
In case of errors in any of these functions
(e.g., a syntax error in your configuration file),
the call returns a non-zero error code
and pushes the error message onto the stack.
As usual, our program uses lua_tostring
with index -1 to get
the message from the top of the stack.
(We defined the error
function in Section 24.1.)
After running the chunk,
the program needs to get the values of the
global variables.
For that,
it calls twice lua_getglobal
,
whose single parameter (besides the omnipresent lua_State
)
is the variable name.
Each call pushes the corresponding global value onto the top of the stack,
so that the width will be at index -2
and the height at index -1 (at the top).
(Because the stack was previously empty,
you could also index from the bottom,
using 1 from the first value and 2 from the second.
By indexing from the top, however,
your code would work even if the stack
was not empty.)
Next, our example uses lua_isnumber
to check whether
each value is numeric.
It then uses lua_tonumber
to
convert such values to double
and C does the coercion to int
.
Finally, it closes the Lua state and returns.
Is it worth using Lua? As I said before, for such simple tasks, a simple file with only two numbers in it would be much easier to use than Lua. Even so, the use of Lua brings some advantages. First, Lua handles all syntax details (and errors) for you; your configuration file can even have comments! Second, the user is already able to do more complex configurations with it. For instance, the script may prompt the user for some information, or it can query an environment variable to choose a proper size:
-- configuration file for program `pp' if getenv("DISPLAY") == ":0.0" then width = 300; height = 300 else width = 200; height = 200 endEven in such simple configuration scenarios, it is hard to anticipate what users will want; but as long as the script defines the two variables, your C application works without changes.
A final reason for using Lua is that now it is easy to add new configuration facilities to your program; this easiness creates an attitude that results in programs that are more flexible.
Copyright © 2003–2004 Roberto Ierusalimschy. All rights reserved. |