## 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).

> - Methods
> - Properties

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-2008 VIRT Laboratory. All rights reserved.