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: