Lua + C - uma combinação perfeita
Lua é uma linguagem de script imperativa, procedural, pequena(sério, muito pequena), reflexiva e leve, projetada para expandir aplicações em geral, com o objetivo de agilizar a prototipagem e ser embarcada em softwares complexos.
Embarcar lua em C/C++ por ter sido o pensamento original da linguagem, é algo muito fácil e incrivelmente util.
antes vamos instalar a biblioteca de desenvolvimento do lua no ubuntu:
# apt-get install liblua5.1-0-dev
Agara vamos fazer algo simples: uma função em C que executa instruções em lua
$ cat > 1.c << _EOF_
#include "lua.h"
#include "lauxlib.h"
int main(int argc, char **argv)
{
lua_State *L = luaL_newstate();
luaL_openlibs(L);
luaL_dostring(L, "print('Hey hey hey, '.._VERSION)");
return 0;
}
_EOF_
compilar, lembrando de linkar a biblioteca do lua e adicionar ao include:
$ gcc -I/usr/include/lua5.1 -o 1 1.c -llua5.1 -lm $ ./1 Hey hey hey, Lua 5.1
Ok, funcionou. Fazer o C carregar um arquivo contendo o script em lua é igualmente trivial, muda apenas a instrução luaL_dostring() por luaL_dofile(), visto a seguir:
$ cat > 2.c << _EOF_
#include "lua.h"
#include "lauxlib.h"
int main(int argc, char **argv)
{
lua_State *L = luaL_newstate();
luaL_openlibs(L);
luaL_dofile(L, "dois.lua");
return 0;
}
_EOF_
E criar o script “dois.lua” que será carregado. Neste caso, não estou gerenciando erros, mas é um código em C, todos os erros devem ser checados ou vai crashar tudo.
$ cat > dois.lua << _EOF_ print "go go go" for i=1,5 do print(i) end print "hell yeah!" _EOF_
compilar igualmente e rodar:
$ gcc -I/usr/include/lua5.1 -o 2 2.c -llua5.1 -lm $ ./2 go go go 1 2 3 4 5 hell yeah!
Lembrando que o script pode ser mudado depois da compilação, esta é a ideia, na verdade haha.
Até aqui, tudo bem. Agora vamos fazer o lua acessar uma função do C:
$ car > 3.c << _EOF_
#include "lua.h"
#include "lauxlib.h"
static int huehue(lua_State *L){ /* método que será chamado dentro do script */
int n = lua_gettop(L); /* numero de argumentos */
double sum = 0;
int i;
for (i = 1; i <= n; i++){
sum += lua_tonumber(L, i);
}
lua_pushnumber(L, sum / n); /* envia primeira resposta */
lua_pushnumber(L, sum); /* envia segunda resposta */
lua_pushnumber(L, 666); /* envia terceira resposta */
return 3; /* quantidade de respostas */
}
int main(int argc, char **argv)
{
lua_State *L = luaL_newstate();
luaL_openlibs(L);
lua_register(L, "huehue", huehue);
luaL_dofile(L, "tres.lua");
return 0;
}
_EOF_
e o arquivo lua:
$ cat > tres.lua << __EOF__
print("arquivo lua\n")
_r, _s, _t = huehue(1,2,3,5,8,9)
print(_r.." - ".._s.." - ".._t)
__EOF__
A compilação continua a mesma:
$ gcc -I/usr/include/lua5.1 -o 3 3.c -llua5.1 -lm $ ./3 arquivo lua 4.6666666666667 - 28 - 666
Beleza, so lebrar de registrar a função que se quer exportar para o script lua e tudo funciona muito bem. Agora a ultima fronteira, fazer o C carregar uma função do lua. Para que isso? bom, vamos dizer que está extraindo dados do hardware de alguma forma em C, mas lidar com isso é complexo ou exige várias mudanças. Re-escrever e re-compilar não é exatamente a saída mais agradavel. Lua pode ser a resposta. O exemplo que estou colocando, é, entretanto, mais simples. O C para dois parametros para uma função continha, que na prática executa o teorema de pitagoras, mas pode ser mudado para qualquer coisa sem requerer recompilação
$ cat > 4.c << _EOF_
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
int main()
{
double z;
lua_State *L = lua_open();
luaL_openlibs(L);
luaL_loadfile(L, "quatro.lua"); /* arquivo lua */
lua_pcall(L, 0, 0, 0); /* limpa a pilha */
lua_getglobal(L, "continha"); /* nome da função do lua */
lua_pushnumber(L, 3); /* envia primeiro argumento */
lua_pushnumber(L, 4); /* envia segundo argumento */
lua_pcall(L, 2, 1, 0);
z = lua_tonumber(L, -1); /* pega resultados */
printf("Resultado: %f\n",z);
lua_pop(L, 1);
lua_close(L);
return 0;
}
_EOF_
e o arquivo lua:
$ cat > quatro.lua << _EOF_
function continha (x, y)
return math.sqrt(x^2 + y^2)
end
_EOF_
Como sempre, a compilação é a mesma:
$ gcc -I/usr/include/lua5.1 -o 4 4.c -llua5.1 -lm $ ./4 Resultado: 5.000000
Lindo! Como podemos ver, embarcar lua em c não só faz sentido, como pode facilitar muito a extensão de um software mais complexos. E é por isto que é tão udada em jogos e em aplicações mobile(compiladas com c++). Usem lua, é uma coisa linda! haha