TPaxInvoke component for Delphi and Borland C++ Builder.


The TPaxInvoke component allows you to dynamically invoke both script-defined (created with paxCompiler) and host-defined methods and global functions. The supported calling conventions are: register (Borland fastcall), cdecl, stdcall, safecall, pascal and msfastcall (Microsoft fastcall). The TPaxInvoke is a part of paxCompiler package, but you can also use it as a stand alone component to call any host-defined or dll-defined function. In particular, the component gives you a flexible way to invoke functions with msfastcall convention.

Demos.

  1. Invoke a host-defined function.
    type
      TCharRec = record
        X, Y: Char;
      end;
    
    function MyHostFunc(const U, V: TCharRec): String; stdcall;
    begin
      result := U.X + V.Y;
    end;
    
    var
      R: TCharRec;
      S: String;
    begin
      R.X := 'a';
      R.Y := 'b';
    
      PaxInvoke1.Address := @ MyHostFunc;
      PaxInvoke1.This := nil; // this is not a method
      PaxInvoke1.ClearArguments;
      PaxInvoke1.AddArgAsRecord(R, SizeOf(R));
      PaxInvoke1.AddArgAsRecord(R, SizeOf(R));
      PaxInvoke1.SetResultAsAnsiString;
      PaxInvoke1.CallConv := _ccSTDCALL;
      PaxInvoke1.CallHost; // call host-defined function
      S := String(PaxInvoke1.GetResultPtr^);
      ShowMessage(S);
    
      PaxInvoke1.ClearResult;
    
  2. Invoke a host-defined method.
    function TForm1.MyHostMethod(const X, Y: ShortString; Z: Integer): String;
    begin
      result := X + Y + IntToStr(Z);
    end;
    
    procedure TForm1.Button3Click(Sender: TObject);
    begin
      PaxInvoke1.Address := @ TForm1.MyHostMethod;
      PaxInvoke1.This := Self; // we call a method
      PaxInvoke1.ClearArguments;
      PaxInvoke1.AddArgAsShortString('xyz');
      PaxInvoke1.AddArgAsShortString('uv');
      PaxInvoke1.AddArgAsInteger(8);
      PaxInvoke1.SetResultAsAnsiString;
      PaxInvoke1.CallConv := _ccREGISTER;
      PaxInvoke1.CallHost;
      ShowMessage(String(PaxInvoke1.GetResultPtr^));
    
      PaxInvoke1.ClearResult;
    end;
    
  3. Invoke a dll-defined function.
    // Point  __msfastcall ret_struct(int x, int y, int z);
    
    type
      TMyPoint = record
        x, y, z: Integer;
      end;
    var
      r: TMyPoint;
    begin
      PaxInvoke1.This := nil; // this is not a method
      PaxInvoke1.CallConv := _ccMSFASTCALL;
    
      PaxInvoke1.LoadAddress('CppDll.dll', 'ret_struct');
      PaxInvoke1.ClearArguments;
      PaxInvoke1.AddArgAsInteger(2);
      PaxInvoke1.AddArgAsInteger(3);
      PaxInvoke1.AddArgAsInteger(5);
      PaxInvoke1.SetResultAsRecord(SizeOf(TMyPoint));
      PaxInvoke1.CallHost; // call dll-defined function
      r := TMyPoint(PaxInvoke1.GetResultPtr^);
      ShowMessage(IntToStr(r.x) + ' ' + IntToStr(r.y) + ' ' + IntToStr(r.z));
    end;
    
  4. Invoke a script-defined function.
    uses
      IMPORT_SysUtils;
    
    procedure Print(const S: String);
    begin
      ShowMessage(S);
    end;
    
    var
      H_MyFunc: Integer;
      I: Integer;
      P: Pointer;
    begin
    {$O-}
      PaxCompiler1.Reset;
      PaxCompiler1.RegisterLanguage(PaxPascalLanguage1);
      PaxCompiler1.RegisterHeader(0, 'procedure Print(const S: String);', @Print);
    
      PaxCompiler1.AddModule('1', PaxPascalLanguage1.LanguageName);
      PaxCompiler1.AddCode('1', 'uses SysUtils;');
      PaxCompiler1.AddCode('1', 'function MyFunc(U, V: Integer): Currency; cdecl;');
      PaxCompiler1.AddCode('1', 'begin');
      PaxCompiler1.AddCode('1', '  try');
      PaxCompiler1.AddCode('1', '    result := U / V;');
      PaxCompiler1.AddCode('1', '  except');
      PaxCompiler1.AddCode('1', '    on E: Exception do');
      PaxCompiler1.AddCode('1', '    begin');
      PaxCompiler1.AddCode('1', '      print(E.Message);');
      PaxCompiler1.AddCode('1', '      result := 7;');
      PaxCompiler1.AddCode('1', '    end;');
      PaxCompiler1.AddCode('1', '  end;');
      PaxCompiler1.AddCode('1', 'end;');
      PaxCompiler1.AddCode('1', 'begin');
      PaxCompiler1.AddCode('1', 'end.');
    
      if PaxCompiler1.Compile(PaxProgram1) then
      begin
        H_MyFunc := PaxCompiler1.GetHandle(0, 'MyFunc', true);
    
        P := PaxProgram1.GetAddress(H_MyFunc); // get address of script-defined function
    
        PaxInvoke1.Address := P;
        PaxInvoke1.This := nil; // this is not a method, but global function.
        PaxInvoke1.ClearArguments;
        PaxInvoke1.AddArgAsInteger(8);
        PaxInvoke1.AddArgAsInteger(2);
        PaxInvoke1.SetResultAsCurrency;
        PaxInvoke1.CallConv := _ccCDECL;
    
        PaxProgram1.SetEntryPoint(PaxInvoke1);
        PaxProgram1.Run;
    
        ShowMessage(CurrToStr(Currency(PaxInvoke1.GetResultPtr^)));
      end
      else
        for I:=0 to PaxCompiler1.ErrorCount do
          ShowMessage(PaxCompiler1.ErrorMessage[I]);
    end;
    


Copyright © 2006-2017 VIRT Laboratory. All rights reserved.