[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- 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); (*)
> 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.