It’s been a while since I last wrote a programming article! I’m working on a big visual fx tool for my company, and I recently started to think that it would be nice to be able to script it. For example, create a small script to convert all texture paths of the effect from absolute to relative, etc.
And I found out that it’s really simple. I decided to use Lua which I (re)discovered through the wonderfull Premake project. So first thing first, go to Lua’s website and download it. Then just create a simple console application, and add all the .c files found in lua/src to your project, except lua.c and luac.c !
For my purpose, I just need to be able to execute some Lua, and access my tool’s functionalities from it. The first step is really simple:
// init lua lua_State* lua = luaL_newstate(); // load the default libs (io, etc.) luaL_openlibs(lua); // then you can load and execute an existing script: luaL_dofile(lua, "test.lua"); // or directly execute something: luaL_dostring(lua, "io.write(\"Hello World!\")"); // and close lua_close(lua);
Yes, it’s that simple.
Then the second part is allowing a Lua script to call a C function. This is also pretty simple:
// our function. All functions that will be called from Lua
// need to have the same signature.
int test(lua_State* lua)
{
// since lua allow calling a function with variable arguments,
// get the number of arguments it was called with.
int num_args = lua_gettop(lua);
// do some tests (we could also just print a message and return)
// note: arguments are retrieved from the lua state object. Since the
// very first value is the number of arguments, the arguments start
// at index 1.
assert(num_args >= 1 && num_args <= 2);
assert(lua_isnumber(lua, 1));
// get the first parameter
int a = lua_tointeger(lua, 1);
// check if we need to print
if(num_args == 2 && lua_isboolean(lua, 2) && lua_toboolean(lua, 2))
{
std::cout << "result: " << a * a << std::endl;
}
// push as many return values that you want, and return the number of
// values that you pushed. In our case it's only 1, but it could be
// really powerful: need to return a list of selected items ? Just
// push all of them and return the number of items.
lua_pushnumber(lua, a * a);
return 1;
}
// somewhere else, start Lua
lua_State* lua = luaL_newstate();
luaL_openlibs(lua);
// push our function on top of the lua state object
lua_pushcfunction(lua, testFunction);
// then make this function globally accessible through the name "test"
lua_setglobal(lua, "test");
// call our function. That's all :)
luaL_dostring(lua, "test(10, true)");
luaL_dostring(lua, "io.write(test(10))");
// close lua
lua_close(lua);
Now if you want to go further, here are a few links: