FPC и Lua


///////////////////////////////////////////////
// script.lua
///////////////////////////////////////////////

function F1()
    SAY_FROM_LUA("F1(): returns 5")
    return 5
end

function F2(A, B, C)
    SAY_FROM_LUA("F2(): F2("..A..","..B..","..C..") returns 10, (A+B+C)")
    local D = A + B + C
    return 10, D
end

function F3()
    SAY_FROM_LUA("F3(): "..A..", "..B.." returns (A+B)")
    C = A + B
    A = A * 2
    B = B * 2
    return C
end

function F4(foo)
    SAY_FROM_LUA("F4(): "..#foo)
    for i = 1, #foo do
      print(i, foo[i])
    end
end

function F5(foo)
    SAY_FROM_LUA("F5(): "..#foo)
    for k,v in pairs(foo) do
      print(k, v)
    end
    return { x=1, y=2 }
end

function F6(foo, ...)
    SAY_FROM_LUA("F6(): "..type(foo)..arg.n)
    foo("F6()")
end

function F7()
    SAY_FROM_LUA("F7() ")
    return { 10,20,30,40,50 }
end

///////////////////////////////////////////////
// program.pas
///////////////////////////////////////////////

uses  lua, lualib, lauxlib;

function SAY_FROM_LUA(L:Plua_State=nil):LongInt; cdecl;
var i,N : integer;
begin
  // N = количество аргументов переданных из Lua
  N := lua_gettop(L);
  // Печать всех остальных документов
  for i:=1 to N do
    writeln('SAY_FROM_LUA: ',lua_tostring(L, i));
end;

// Установка переменной в скрипте Lua
procedure SetInt(L: Plua_State; VarName: PChar; VarValue: integer);
begin
  lua_pushinteger(L, VarValue); // Загружаем значение переменной "VarName"
  lua_setglobal (L, VarName);  // Указываем имя переменной в скрипте
  // аналогично: pushnil, pushnumber, pushstring, pushboolean, pushcclosure
end;

// Получение переменной из скрипта Lua
function GetInt(L: Plua_State; VarName: PChar): integer;
begin
    lua_getglobal(L, VarName);       // Находим переменную по имени "VarName"
    Result := lua_tointeger(L, -1);  // Вытаскиваем её значение
    // -1 означает что возвращем значение выше найденной переменной
    // аналогично: tonumber, tostring, toboolean, topointer
end;

function callback(L: Plua_State): Integer; cdecl;
var N,i:integer;
begin
  N := lua_gettop(L);
  writeln('callback() params count: ',N);
  for i:=1 to N do
    writeln('param: ',lua_tostring(L, i));
  Result:=1;
end;

var
  L: Plua_State;
  i: integer;
begin
  L := lua_open;
  if (L = nil) then
  begin
      writeln('Lua engine not loaded! Terminating!');
      exit;
  end;
  luaL_openlibs(L);

  // Подгружаем строку
  writeln;
  lua_dostring(L, 'return 1,A,"a"');
  writeln('Num results:', lua_gettop(L));
  writeln('Result 1:', lua_tostring(L,1));
  writeln('Result 2:', lua_tostring(L,2));
  writeln('Result 3:', lua_tostring(L,3));
  lua_settop(L,0);

  // Подгружаем и связываем Lua-скрипт
  lua_dofile(L, 'script.lua');
  lua_register(L, 'SAY_FROM_LUA', @SAY_FROM_LUA);

  // Вызываем F1(): вытаскиваем её на вершину стека и вызываем
  writeln;
  lua_getfield(L, Lua_GlobalsIndex, 'F1');
  // call: 0 args, 1 result
  lua_call(L, 0, 1);
  writeln('F1() number of results:', lua_gettop(L));
  writeln('F1() result:', lua_tointeger(L,1));
  // Чистим стек
  lua_pop(L, 1);

  // Вызываем F2()
  writeln;
  lua_getfield(L, Lua_GlobalsIndex, 'F2');
  lua_pushnumber(L, 1);
  lua_pushnumber(L, 2);
  lua_pushnumber(L, 3);
  // call: 3 args, 2 results
  if lua_pcall(L, 3, 2, 0)<>0 then
      writeln('Error: ', lua_tostring(L, -1))
  else
  begin
      writeln('F2() number of results: ', lua_gettop(L));
      for i:=1 to lua_gettop(L) do
          writeln('F2() result: ',lua_tostring(L, i));
      for i:=lua_gettop(L) downto 1 do
          lua_pop(L, i);
  end;

  // Вызываем F3(): с глобальными параметрами
  writeln;
  lua_getfield(L, Lua_GlobalsIndex, 'F3');
  SetInt(L,'A',20);
  SetInt(L,'B',30);
  // call: 0 args, 1 result
  lua_call(L, 0, 1);
  writeln('F3() number of results: ', lua_gettop(L));
  writeln('Results: ',GetInt(L,'A'), ', ', GetInt(L,'B'));
  lua_settop(L,0);

  // Вызываем F4(): с таблицей
  writeln;
  lua_getfield(L, Lua_GlobalsIndex, 'F4');
  lua_newtable(L);
  for i := 1 to 3 do
  begin
      lua_pushinteger(L, i);   // index
      lua_pushinteger(L, i*2); // value
      lua_rawset(L, -3);       // Store the pair
  end;
  // call: 1 args, 0 results
  lua_call(L, 1, 0);
  writeln('F4() number of results: ', lua_gettop(L));

  // Вызываем F5(): с хешем туда и обратно
  writeln;
  lua_getfield(L, Lua_GlobalsIndex, 'F5');
  lua_newtable(L);
  for i := 1 to 3 do
  begin
      lua_pushstring(L, copy('xxxxxx',1,i));   // index
      lua_pushinteger(L, i*2); // value
      lua_rawset(L, -3);       // Store the pair
  end;
  // call: 1 args, 1 results
  lua_call(L, 1, 1);
  writeln('F5() number of results: ', lua_gettop(L));
  writeln(lua_typename(L,lua_type(L,1)));
  lua_pushstring(L,'x');
  lua_gettable(L,1);
  writeln('Value x:', lua_tostring(L,-1));
  lua_pushstring(L,'y');
  lua_gettable(L,1);
  writeln('Value y:', lua_tostring(L,-1));
  lua_settop(L,0);

  // Вызываем F6(): с callback
  writeln;
  lua_getfield(L, Lua_GlobalsIndex, 'F6');
  lua_pushcclosure(L, @callback, 0); // value
  // call: 1 args, 0 results
  lua_call(L, 1, 0);
  writeln('F6() number of results: ', lua_gettop(L));

  lua_getfield(L, Lua_GlobalsIndex, 'F7');
  lua_call(L, 0, -1);
  writeln('F7() number of results: ', lua_gettop(L));

  lua_pushnil(L);
  while (lua_next(L, 1) <> 0) do
  begin
      writeln(lua_tostring(L,-1));
      lua_pop(L, 1);
  end;

  lua_close(L);

end.