nielsAD / lape

Scripting engine with Pascal-like syntax for FPC and Delphi
118 stars 28 forks source link

Run script function\procedure with parms and result from native pascal #196

Closed zamtmn closed 9 months ago

zamtmn commented 10 months ago

Do we have the opportunity to run a separate function in script without running the script as a whole? naturally, from native pascal code, send the parameters to her and taking the result? Please show an example of doing this if possible

Vizit0r commented 10 months ago

long time ago, when i try to achive lape to working state, i use construction like

  Result := LapeCompiler.Compile();
....
  if Result then
  begin
    PPCode := LapeCompiler.Emitter.Code;
    CodeLen := LapeCompiler.Emitter.CodeLen;
  end;

function TBaseLapeScriptThread.execfunction(ProcName : String; Params : array of Variant; IsEvent : Boolean = False) : Variant;
var ParamVars : TObjectList<TLapeGlobalVar>;
    m : TLapeType_Method;
    i : Integer;
    VarStack2: lptypes.TByteArray;

  function getVar(BaseType: TLapeType; Value: String) : lptypes.TByteArray;
  var LapeVar : TLapeGlobalVar;
  begin
    LapeVar := BaseType.NewGlobalVarStr(Value);
    ParamVars.Add(LapeVar);
    SetLength(Result, LapeVar.Size);
    Move(PPointer(LapeVar.Ptr)^, Result[0], LapeVar.Size);
  end;

begin
  if not Assigned(LapeCompiler) then
    Exit;
  if (not Assigned(LapeCompiler[ProcName])) then
  begin
    ExecEvMethodError := 'Error exec method: - Method with name "' + ProcName + '" is not exists!';
    Exit;
  end;
  if not Assigned(LapeCompiler[ProcName].VarType) then
  begin
    ExecEvMethodError := 'Error exec method: - Method with name "' + ProcName + '" has incorrect type!';
    Exit;
  end;
  m := TLapeType_Method(LapeCompiler[ProcName].VarType);

  if Length(Params) < m.Params.Count then
  begin
    ExecEvMethodError := Format('Error exec method: Wrong number of parameters found (%d), expected %d',
                                [Length(Params), m.Params.Count]);
    Exit;
  end;

  //pushing params & vars to stack
  ParamVars := TObjectList<TLapeGlobalVar>.Create;

  for i := 0 to m.Params.Count - 1 do
    VarStack2 := VarStack2 + getVar(m.Params[i].VarType, VarToStr(Params[i]));

  if Assigned(m.Res) then
    VarStack2 := VarStack2 + getVar(m.Res, Result);

//lpinterpreter.pas
  RunCode(PPCode, CodeLen, VarStack2, PCodePos(LapeCompiler[ProcName].Ptr)^);

  ParamVars.Free;

  if not ExecEvMethodError.IsEmpty and ValidObject(CharObj) then
    Script_AddToSystemJournal(ExecEvMethodError);
end;

maybe will be useful for you.

ollydev commented 10 months ago

You can do above, but you have to construct everything yourself.

Using lape's libffi interface is ideal for this. You can generate a native method which will call a script method.

Some lape code...

function test(a, b: Int32): String;
begin
  Result := IntToStr(a) + '-' + IntToStr(b);
end;

In FPC after script has been compiled, this will call the above lape function

uses
  lpffiwrappers;

type
  TMyTest = function(a, b: Integer): String;

WriteLn(TMyTest(LapeExportWrapper(Compiler['test']).Func)(123,456)); 
zamtmn commented 10 months ago

Vizit0r Thanks!

ollydev There is a way to first make sure that the procedure in the script has exactly such a declaration?

ollydev commented 10 months ago
      methodType := TLapeType_Method(TLapeGlobalVar(Compiler['Test']).VarType);
      WriteLn(methodType.Params.Count);
      WriteLn(methodType.Params[0].VarType.Name);
      WriteLn(methodType.Res.Name);
zamtmn commented 10 months ago

Thanks! It's nice to have a quick response!

Vizit0r commented 10 months ago

Using lape's libffi interface is ideal for this.

yes, if you use lape only in windows :)

zamtmn commented 10 months ago

doesn't ffi work on linux?

ollydev commented 10 months ago

it does work fine on other platforms.

Vizit0r commented 10 months ago

it does work fine on other platforms.

But not all of them, thats why i have to do those strange things with script methods execution :)

ollydev commented 10 months ago

Do you have any examples? All current tests pass image

Vizit0r commented 9 months ago

Do you have any examples? All current tests pass

https://github.com/nielsAD/lape/issues/170

zamtmn commented 9 months ago

Thanks! This can be closed. If there are problems, I will make a new report