Added exception handling for registered functions

Added HasValue method for tables
Fixed LuaFunction DataType not being recognized as VariableFunction
This commit is contained in:
Mark van Renswoude 2017-05-28 16:34:32 +02:00
parent b250054d26
commit 47b39799f3
4 changed files with 81 additions and 6 deletions

2
.gitignore vendored
View File

@ -1 +1 @@
/__history/
__history

View File

@ -194,8 +194,8 @@ var
lua_pushunsigned: procedure(L: lua_State; n: lua_Unsigned); cdecl;
lua_pushlstring: function (L: lua_State; s: PAnsiChar; l_: size_t): PAnsiChar; cdecl;
lua_pushstring: function (L: lua_State; s: PAnsiChar): PAnsiChar; cdecl;
lua_pushvfstring: function (L: lua_State; fmt: PAnsiChar; argp: array of const): PAnsiChar; cdecl;
lua_pushfstring: function (L: lua_State; fmt: PAnsiChar): PAnsiChar; cdecl;
lua_pushvfstring: function (L: lua_State; fmt: PAnsiChar; argp: Pointer): PAnsiChar; cdecl;
lua_pushfstring: function (L: lua_State; fmt: PAnsiChar; argp: Pointer): PAnsiChar; cdecl;
lua_pushcclosure: procedure(L: lua_State; fn: lua_CFunction; n: Integer); cdecl;
lua_pushboolean: procedure(L: lua_State; b: Integer); cdecl;
lua_pushlightuserdata: procedure(L: lua_State; p: Pointer); cdecl;
@ -408,6 +408,10 @@ type
var
luaL_setfuncs: procedure(L: lua_State; luaL_Reg: PluaL_Reg; nup: Integer); cdecl;
procedure luaL_where(L: lua_State; level: Integer);
function luaL_error(L: lua_State; fmt: PAnsiChar; argp: Pointer): Integer;
const
DefaultLuaLibName = 'lua' + LUA_VERSION_MAJOR + LUA_VERSION_MINOR + '.dll';
@ -727,6 +731,33 @@ begin
Result := lua_tolstring(L, idx, nil);
end;
procedure luaL_where(L: lua_State; level: Integer);
var
ar: lua_Debug;
msg: AnsiString;
begin
if (lua_getstack(L, level, ar) <> 0) then // check function at level
begin
lua_getinfo(L, 'Sl', ar); // get info about it
if (ar.currentline > 0) then // is there info?
begin
msg := Format('%s:%d: ', [ar.short_src, ar.currentline]);
lua_pushlstring(L, PAnsiChar(msg), Length(msg));
exit
end;
end;
lua_pushliteral(L, ''); // else, no information available...
end;
function luaL_error(L: lua_State; fmt: PAnsiChar; argp: Pointer): Integer;
begin
luaL_where(L, 1);
lua_pushvfstring(L, fmt, argp);
lua_concat(L, 2);
Result := lua_error(L);
end;
initialization
finalization

28
Lua.pas
View File

@ -40,6 +40,7 @@ type
ELuaUnsupportedParameterException = class(ELuaException);
ELuaUnsupportedVariableException = class(ELuaException);
ELuaNoFunctionException = class(ELuaException);
ELuaNativeCodeException = class(ELuaException);
TLuaLibrary = (Base, Coroutine, Table, IO, OS, StringLib, Bit32, Math, Debug, Package, All);
TLuaLibraries = set of TLuaLibrary;
@ -127,6 +128,7 @@ type
['{57FD52A1-7D53-485B-A630-29841C498387}']
function GetEnumerator: ILuaTableEnumerator;
function HasValue(AKey: TLuaImplicitVariable): Boolean;
function GetValue(AKey: TLuaImplicitVariable): ILuaVariable;
procedure SetValue(AKey: TLuaImplicitVariable; AValue: TLuaImplicitVariable);
end;
@ -165,6 +167,7 @@ type
{ ILuaTable }
function GetEnumerator: ILuaTableEnumerator;
function HasValue(AKey: TLuaImplicitVariable): Boolean;
function GetValue(AKey: TLuaImplicitVariable): ILuaVariable;
procedure SetValue(AKey: TLuaImplicitVariable; AValue: TLuaImplicitVariable);
end;
@ -666,6 +669,7 @@ begin
LuaBoolean: Result := VariableBoolean;
LuaString: Result := VariableString;
LuaTable: Result := VariableTable;
LuaFunction: Result := VariableFunction;
LuaUserData: Result := VariableUserData;
LuaLightUserData: Result := VariableUserData;
else
@ -1081,6 +1085,11 @@ begin
end;
function TLuaTable.HasValue(AKey: TLuaImplicitVariable): Boolean;
begin
Result := FTable.ContainsKey(AKey);
end;
function TLuaTable.GetValue(AKey: TLuaImplicitVariable): ILuaVariable;
begin
Result := FTable[AKey];
@ -1308,8 +1317,16 @@ end;
procedure TLua.LoadFromFile(const AFileName: string; AAutoRun: Boolean; const AChunkName: string);
var
chunkName: string;
begin
LoadFromScript(TLuaScript.Create(TFileStream.Create(AFileName, fmOpenRead or fmShareDenyNone), soOwned), soOwned, AAutoRun, AChunkName);
if Length(AChunkName) > 0 then
chunkName := AChunkName
else
chunkName := ExtractFileName(AFileName);
LoadFromScript(TLuaScript.Create(TFileStream.Create(AFileName, fmOpenRead or fmShareDenyNone), soOwned), soOwned, AAutoRun, chunkName);
end;
@ -1670,8 +1687,13 @@ begin
begin
context := TLuaContext.Create(State);
RegisteredFunctions[ACookie](context);
Result := context.Result.Count;
try
RegisteredFunctions[ACookie](context);
Result := context.Result.Count;
except
on E:Exception do
Result := luaL_error(State, PAnsiChar(AnsiString(E.Message)), nil);
end;
end;
end;

View File

@ -33,6 +33,7 @@ type
procedure Input;
procedure Output;
procedure DelphiFunction;
procedure DelphiFunctionException;
procedure LuaFunction;
procedure LuaFunctionDefaultResult;
procedure LuaFunctionString;
@ -197,6 +198,27 @@ begin
end;
procedure TTestWrapper.DelphiFunctionException;
begin
Lua.RegisterFunction('crazyharry',
procedure(AContext: ILuaContext)
begin
raise Exception.Create('Boom!');
end);
try
Lua.LoadFromString('print(crazyharry("Did somebody say dynamite?"))');
Fail('ELuaNativeCodeException expected');
except
on E:Exception do
begin
CheckIs(E, ELuaException);
CheckEquals('[string "?"]:1: Boom!', E.Message);
end;
end;
end;
procedure TTestWrapper.LuaFunction;
var
returnValues: ILuaReadParameters;