Lua is lighweight programing language designed for embedding, it was created in 1993 by Roberto Ierusalimschy, Luiz Henrique de Figueiredo, and Waldemar Celes.
Lua even has a very fast LuaJIT which sadly I cannot use since I'm aiming for embedded MCU.
Installation of the Lua library was very simple, download the release, extract it in the lib folder and add library.json.
To gain the performance I needed, I've modified luaconf.h
1 2 3 | /* Default configuration ('long long' and 'double', for 64-bit Lua) */ #define LUA_INT_DEFAULT LUA_INT_INT #define LUA_FLOAT_DEFAULT LUA_FLOAT_FLOAT |
To initialize Lua a new state is created and the default libraries added to it
1 2 3 4 5 6 7 8 9 | lua_State *L = luaL_newstate(); /* create state */ if (L == NULL) { l_message(argv[0], "cannot create state: not enough memory"); return EXIT_FAILURE; } printf("setting libs\r\n"); luaL_openlibs(L); |
Next is injecting the demo function into the state
1 2 3 | function transform(a,b) return (a^2/math.sin(2*math.pi/b))-(a/2) end |
1 2 3 4 5 6 7 8 9 10 11 12 | char *code = "function transform(a,b)\r\n \ return (a^2/math.sin(2*math.pi/b))-(a/2)\r\n \ end\r\n"; if (luaL_loadstring(L, code) == LUA_OK) { if (lua_pcall(L, 0, 0, 0) == LUA_OK) { // If it was executed successfully we remove the code from the stack lua_pop(L, lua_gettop(L)); } } |
And to run the transform function, the function name is pushed along with its arguments, the function is called and the result is pulled back from the stack
1 2 3 4 5 6 | lua_getglobal(L, "transform"); lua_pushnumber(L, i); lua_pushnumber(L, i); lua_call(L, 2, 1); double res = lua_tonumber(L, -1); |
Summary
Lua was the easiest to integrate, it is the fastest scripting engine and if speed is your primary concern it should be one of the top candidates.
In my particular use case:
- x64 native vs Lua slow down is about 4x times
- ESP32 native vs Lua slow down is about 20x times
As always you can find the fruits of my labor at my GitHub account.
0 comments:
Post a Comment