Using Lua with C++: A short tutorial
Using Lua is easy! In this short tutorial we'll show how to write a fully working host-program in C++ with Lua callbacks.
Since the static Lua libraries are written in C, you must import them as such:
extern "C" { #include "lua.h" } int main() { lua_State *L = lua_open(); lua_close(L); return 0; }
Compiling and linking with GNU g++:
g++ host.cpp -o host -Ilua-5.0.2/include/ -Llua-5.0.2/lib/ -llua
Including lualib.h and lauxlib.h makes it easy to write a fully working host:
#include <iostream> extern "C" { #include "lua.h" #include "lualib.h" #include "lauxlib.h" } void report_errors(lua_State *L, int status) { if ( status!=0 ) { std::cerr << "-- " << lua_tostring(L, -1) << std::endl; lua_pop(L, 1); // remove error message } } int main(int argc, char** argv) { for ( int n=1; n<argc; ++n ) { const char* file = argv[n]; lua_State *L = lua_open(); luaopen_io(L); // provides io.* luaopen_base(L); luaopen_table(L); luaopen_string(L); luaopen_math(L); luaopen_loadlib(L); std::cerr << "-- Loading file: " << file << std::endl; int s = luaL_loadfile(L, file); if ( s==0 ) { // execute Lua program s = lua_pcall(L, 0, LUA_MULTRET, 0); } report_errors(L, s); lua_close(L); std::cerr << std::endl; } return 0; }
Compilation and linking:
g++ host.cpp -o host -Ilua-5.0.2/include/ -Llua-5.0.2/lib/ -llua -llualib
Let's test this with some Lua programs. The files here are from the distribution, hello.lua is simply:
-- the first program in every language io.write("Hello world, from ",_VERSION,"!/n")
Executing a couple of Lua programs with our host program produces:
[csl@eris:~/dev/lua/lua-5.0.2]$ ./host test/hello.lua test/printf.lua -- Loading file: test/hello.lua Hello world, from Lua 5.0.2! -- Loading file: test/printf.lua Hello csl from Lua 5.0.2 on Wed Mar 2 13:13:05 2005
It gets very interesting when Lua programs call your own functions. In the following program, we define a function my_function() and register it with the Lua environment using lua_register(). Our function prints its arguments as strings and returns the integer value of 123.
#include <iostream> extern "C" { #include "lua.h" #include "lualib.h" #include "lauxlib.h" } int my_function(lua_State *L) { int argc = lua_gettop(L); std::cerr << "-- my_function() called with " << argc << " arguments:" << std::endl; for ( int n=1; n<=argc; ++n ) { std::cerr << "-- argument " << n << ": " << lua_tostring(L, n) << std::endl; } lua_pushnumber(L, 123); // return value return 1; // number of return values } void report_errors(lua_State *L, int status) { if ( status!=0 ) { std::cerr << "-- " << lua_tostring(L, -1) << std::endl; lua_pop(L, 1); // remove error message } } int main(int argc, char** argv) { for ( int n=1; n<argc; ++n ) { const char* file = argv[n]; lua_State *L = lua_open(); luaopen_io(L); // provides io.* luaopen_base(L); luaopen_table(L); luaopen_string(L); luaopen_math(L); luaopen_loadlib(L); // make my_function() available to Lua programs lua_register(L, "my_function", my_function); std::cerr << "-- Loading file: " << file << std::endl; int s = luaL_loadfile(L, file); if ( s==0 ) { // execute Lua program s = lua_pcall(L, 0, LUA_MULTRET, 0); } report_errors(L, s); lua_close(L); std::cerr << std::endl; } return 0; }
Let's write a small Lua program test.lua to call my_function():
io.write("Running ", _VERSION, "/n") a = my_function(1, 2, 3, "abc", "def") io.write("my_function() returned ", a, "/n")