Lua Printf |
|
printf
string formatting function in Lua.
It's easy to write formatted text in Lua using io.write()
, print()
and string.format()
. io.write
is similar to print
except io.write
does not follow each output with a new line. The C function printf()
can be emulated as:
> io.write(string.format("Hello from %s on %s\n",_VERSION,os.date())) Hello from Lua 5.1 on Mon Jan 1 22:11:56 2007
Or, this can be wrapped in a function as:
printf = function(s,...) return io.write(s:format(...)) end -- function
and then used as
printf("Hello from %s on %s\n",_VERSION,date())
In the above example the format string and the variable argument list from printf()
are passed to string.format()
. write()
prints the resulting formatted string. [*1]
It is interesting to note how the Lua 5.1 syntax for string methods forces the separate treatment of the first argument. This makes sense, because it has a quite separate role from the others.
Note that Lua's string.format
function doesn't support the full C format specification [1], so this function is not a drop-in replacement. If you want the full capabilities of the C format specification, you might want to do the printf
call in C code and call that from Lua. Alternately, you may using the C string functions to emulate the behavior you need entirely in Lua (more work).
The above example could be coded in C as follows. This also optimizes by capturing the two standard library functions as upvalues, rather than looking them up each time (although looking them up each time has the advantage of being more dynamic). You may just want to use the Lua version though.
static int l_printf (lua_State *L) { lua_pushvalue(L, lua_upvalueindex(2)); lua_insert(L, 1); lua_call(L, lua_gettop(L) - 1, 1); lua_pushvalue(L, lua_upvalueindex(1)); lua_pushvalue(L, -2); lua_call(L, 1, 0); return 0; } int luaopen_printf (lua_State *L) { lua_getglobal(L, "io"); lua_getglobal(L, "string"); lua_pushliteral(L, "write"); lua_gettable(L, -3); lua_pushliteral(L, "format"); lua_gettable(L, -3); lua_pushcclosure(L, l_printf, 2); /* With 5.1, I'd probably just return 1 at this point */ lua_setglobal(L, "printf"); return 0; }
A C function l_printf
is registered with Lua as printf
. When l_printf
is called from Lua, format()
is called with the given arguments, then write()
is called with the result of format
and finally the number of results returned.
Footnotes
[*1] The Lua 4 versions were
function printf(...) write(call(format,arg)) end
static int l_printf (lua_State *l) { lua_getglobal(L,"format"); lua_insert(L,1); lua_call(L,lua_gettop(L)-1,LUA_MULTRET); lua_getglobal(L,"write"); lua_insert(L,1); lua_call(L,lua_gettop(L)-1,LUA_MULTRET); return lua_gettop(L); } lua_register(L,"printf",l_printf);
pcall()
wrapper to catch errors and point back to the offending printf()
.
Otherwise it's difficult to know exactly where the error came from.
function printf(...) local function wrapper(...) io.write(string.format(...)) end local status, result = pcall(wrapper, ...) if not status then error(result, 2) end end