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