• Subject: RE: Lua Tutor (Delphi + Lua)
• From: jdarling@...
• Date: Thu, 29 Jun 2006 06:02:33 -0700

```Here is how I call lua methods from Delphi, and so far I've never had a
problem.

type
TVariantArray =array of Variant;
PVariantArray =^TVariantArray;

function LuaPCallFunction(L: Plua_State; FunctionName :String;
const Args: array of Variant;
Results : PVariantArray;
ErrFunc: Integer=0;
NResults :Integer=LUA_MULTRET):Integer;
var
NArgs,
i :Integer;
begin
//Put Function To Call on the Stack
luaPushString(L, FunctionName);
lua_gettable(L, LUA_GLOBALSINDEX);

//Put Parameters on the Stack
NArgs := High(Args)+1;
for i:=0 to (NArgs-1) do
LuaPushVariant(L, Args[i]);

//Call the Function
LuaPcall(L, NArgs, NResults, ErrFunc);
Result :=lua_gettop(L);   //Get Number of Results

if (Results<>Nil)
then begin
//Get Results in the right order
SetLength(Results^, Result);
for i:=0 to Result-1 do
begin
Results^[Result-(i+1)] :=LuaToVariant(L, -(i+1));
end;
end;
end;

function TLUA.FunctionExists(MethodName: String): Boolean;
begin
lua_pushstring(L, PChar(MethodName));
lua_rawget(L, LUA_GLOBALSINDEX);
result := lua_isfunction(L, -1);
lua_pop(L, 1);
end;

function TLUA.CallFunction(FunctionName: String;
const Args: array of Variant; Results: PVariantArray = nil): Integer;
begin
if FunctionExists(FunctionName) then
result := LuaPCallFunction(L, FunctionName, Args, Results)
else
result := -1;
end;

Usage:
LuaInstance.CallFunction('MyFunc', [Param1, Param2], ResultVarArray);

Actually I've also attached my Delphi wrapper unit for lua, its built
around the lua 5.0.2 distro that ships with LuaEdit, but it should be
easily modifiable to 5.1.x

- Jeremy

"Help I suffer from the oxymoron Corporate Security."

> -------- Original Message --------
> Subject: Re: Lua Tutor (Delphi + Lua)
> From: Jilani Khaldi <jilani.khaldi1@virgilio.it>
> Date: Wed, June 28, 2006 5:37 pm
> To: Lua list <lua@bazar2.conectiva.com.br>
>
> // Call add_xy() from Delphi:
> function call_add_xy(L: Plua_State; x, y: Double): Double;
> begin
>    // Push functions and arguments:
>    lua_getglobal(L, 'add_xy');  // Function to be called.
>    lua_pushnumber(L ,x);        // Push 1st argument.
>    lua_pushnumber(L, y);        // push 2nd argument.
>
>    // Do the call (2 arguments, 1 result):
>    if lua_pcall(L, 2, 1, 0) <> 0 then
>    begin
>      // Handle error here.
>    end;
>
>    // Retrieve result:
>    if not lua_isnumber(L, -1) then
>    begin
>      // Handle error here.
>    end;
>    Result := lua_tonumber(L, -1);
>
>    // pop returned value:
>    lua_pop(L, 1);
> end;
>
> procedure TForm1.Button1Click(Sender: TObject);
> var
>   L: Plua_State;
>   FName: PChar;
>   x, y, R: double;
>   st: string;
>   pc: PChar;
> begin
>   FName := 'exp1.lua';
>   L := lua_open();
>   luaopen_base(L);
> //  luaopen_io(L); (*)
>   lua_call(L, 0, 0);
>   x := 3.14159;
>   y := 2.71828;
>   R := call_add_xy(L,x,y);
>   st := Format('pi + e = %1.5f', [R]);
>   lua_close(L);
> end;
>
> exp1.lua file contains:
>
> function add_xy(x, y)
>   return (x + y)
> end
>
> (*): this line gives an "access violation" if the program is run from
> Delphi IDE with lua5.1.dll, but not with lua5.0.dll
>
> jk
```
```unit LuaWrapper;

{\$IFDEF FPC}
{\$MODE Delphi}
{\$ENDIF}

interface

uses
Classes,
LUA,
LuaUtils,
Lauxlib,
LuaLib;

type

{ TLUA }

TLUA=class(TComponent)
private
L : Plua_State;
FScript,
FLibFile,
FLibName: String;
FUseDebugDLL: Boolean;
FMethods : TStringList;
procedure SetLibName(const Value: String);
function GetValue(ValueName: String): Variant;
procedure SetValue(ValueName: String; const Value: Variant);
procedure OpenLibs;
procedure SetUseDebugDLL(const Value: Boolean);
function GetUseDebugDLL: Boolean;
public
constructor Create(Owner : TComponent); override;
destructor Destroy; override;

procedure Close;
procedure Open;

procedure LoadScript(Script : String);
procedure Execute;
procedure ExecuteCmd(Script:String);
procedure RegisterLUAMethod(MethodName: String; Func: lua_CFunction);
function  FunctionExists(MethodName:String) : Boolean;
function  CallFunction( FunctionName :String; const Args: array of Variant;
Results : PVariantArray = nil):Integer;
function  TableFunctionExists(TableName, FunctionName : String) : Boolean;
function  CallTableFunction( TableName, FunctionName :String;
const Args: array of Variant;
Results : PVariantArray = nil):Integer;

property LibName : String read FLibName write SetLibName;
property Value[ValueName:String]:Variant read GetValue write SetValue;
property LuaState : Plua_State read L;
property UseDebugDLL : Boolean read GetUseDebugDLL write SetUseDebugDLL;
end;

implementation

uses
Variants,
SysUtils;

constructor TLUA.Create(Owner: TComponent);
begin
inherited;
FMethods := TStringList.Create;
Open;
end;

destructor TLUA.Destroy;
begin
lua_close(L);
FMethods.Free;
inherited;
end;

procedure TLUA.Execute;
begin
if L = nil then
Open;
if FScript <> '' then
else
if FLibFile <> '' then
else
exit;
LuaPCall(L, 0, 0, 0);
end;

procedure TLUA.ExecuteCmd(Script: String);
begin
luaL_loadbuffer(L, PChar(Script), Length(Script), PChar(LibName));
lua_pcall(L, 0, 0, 0);
end;

function TLUA.GetValue(ValueName: String): Variant;
begin
lua_pushstring(L, PChar(ValueName));
lua_rawget(L, LUA_GLOBALSINDEX);
result := LuaToVariant(L, -1);
lua_pop(L, 1);
end;

begin
if L = nil then
Open;
FLibFile := FileName;
FScript := '';
end;

begin
if FScript <> Script then
Close;
if L = nil then
Open;
FScript := Trim(Script);
FLibFile := '';
if FScript <> '' then
end;

function TLUA.FunctionExists(MethodName: String): Boolean;
begin
lua_pushstring(L, PChar(MethodName));
lua_rawget(L, LUA_GLOBALSINDEX);
result := lua_isfunction(L, -1);
lua_pop(L, 1);
end;

procedure TLUA.RegisterLUAMethod(MethodName: String; Func: lua_CFunction);
begin
if L = nil then
Open;
lua_register(L, PChar(MethodName), Func);
if FMethods.IndexOf(MethodName) = -1 then
else
FMethods.Objects[FMethods.IndexOf(MethodName)] := @Func;
end;

procedure TLUA.SetLibName(const Value: String);
begin
FLibName := Value;
end;

procedure TLUA.SetValue(ValueName: String; const Value: Variant);
begin
if VarIsType(Value, varString) then
LuaSetIdentValue(L, ValueName, quote(Value))
else
LuaSetIdentValue(L, ValueName, Value);
end;

function TLUA.CallFunction(FunctionName: String;
const Args: array of Variant; Results: PVariantArray = nil): Integer;
begin
if FunctionExists(FunctionName) then
result := LuaPCallFunction(L, FunctionName, Args, Results)
else
result := -1;
end;

procedure TLUA.Close;
begin
if L <> nil then
lua_close(L);
L := nil;
end;

procedure TLUA.Open;
begin
if L <> nil then
Close;
L := lua_open;
OpenLibs;
end;

procedure TLUA.OpenLibs;
var
I : Integer;
begin
luaopen_base(L);
luaopen_table(L);
luaopen_io(L);
luaopen_string(L);
luaopen_math(L);
if UseDebugDLL then
luaopen_debug(L);
lua_settop(L, 0);

for I := 0 to FMethods.Count -1 do
begin
RegisterLUAMethod(FMethods[I], Pointer(FMethods.Objects[I]));
end;
end;

procedure TLUA.SetUseDebugDLL(const Value: Boolean);
begin
FUseDebugDLL := Value;
end;

function TLUA.GetUseDebugDLL: Boolean;
begin
result := FUseDebugDLL and (FileExists(ExtractFilePath(ParamStr(0))+'LuaEditDebug.dll'));
end;

function TLUA.CallTableFunction(TableName, FunctionName: String;
const Args: array of Variant; Results: PVariantArray): Integer;
var
NArgs,
NResults,
i :Integer;
begin
if TableFunctionExists(TableName, FunctionName) then
begin
//Put Function To Call on the Stack
luaPushString(L, TableName);
lua_gettable(L, LUA_GLOBALSINDEX);
luaPushString(L, FunctionName);
lua_rawget(L, -2);

//Put Parameters on the Stack
NArgs := High(Args)+1;
for i:=0 to (NArgs-1) do
LuaPushVariant(L, Args[i]);

NResults := LUA_MULTRET;
//Call the Function
LuaPcall(L, NArgs, NResults, 0);
Result :=lua_gettop(L);   //Get Number of Results

if (Results<>Nil) then
begin
//Get Results in the right order
SetLength(Results^, Result);
for i:=0 to Result-1 do
Results^[Result-(i+1)] :=LuaToVariant(L, -(i+1));
end;
end
else
result := -1;
end;

function TLUA.TableFunctionExists(TableName,
FunctionName: String): Boolean;
begin
//  LuaGetTable(L, 1, TableName);
lua_pushstring(L, PChar(TableName));
lua_rawget(L, LUA_GLOBALSINDEX);
result := lua_istable(L, -1);
{  lua_pop(L, 1);

lua_pushstring(L, PChar(TableName));
lua_rawget(L, LUA_GLOBALSINDEX);
result := lua_istable(L, -1);}
if result then
begin
lua_pushstring(L, PChar(FunctionName));
lua_rawget(L, -2);
result := lua_isfunction(L, -1);
lua_pop(L, 1);
lua_pop(L, 1);
end
else
begin
lua_pop(L, 1);
end;
end;

end.
```