lua-users home
lua-l archive

RE: Lua Tutor (Delphi + Lua)

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


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); (*)
> luaL_loadfile(L, FName);
> 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]);
> memo1.Lines.Add(st);
> 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 LoadFile(FileName: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
 LuaLoadBuffer(L, FScript, LibName)
 else
 if FLibFile <> '' then
 luaL_loadfile(L, PChar(FLibFile))
 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;
procedure TLUA.LoadFile(FileName: String);
begin
 if L = nil then
 Open;
 FLibFile := FileName;
 FScript := '';
 luaL_loadfile(L, PChar(FileName));
end;
procedure TLUA.LoadScript(Script: String);
begin
 if FScript <> Script then
 Close;
 if L = nil then
 Open;
 FScript := Trim(Script);
 FLibFile := '';
 if FScript <> '' then
 LuaLoadBuffer(L, Script, LibName);
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
 FMethods.AddObject(MethodName, @Func)
 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);
 luaopen_loadlib(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.

AltStyle によって変換されたページ (->オリジナル) /