かなり昔にInnerfuse Pascal Script 2と言うやつを使った事があったのでその流れをくむRemObjects社のPascal Scriptと、Delphi XE2からバンドルされているFastReport社のFastScriptをとりあえず試してみました。
前は単純なことしかできなかったけど、最近ではアプリで作ったクラスへのアクセスはもちろん、TFormとかにもアクセス出来るみたいです。とりあえず作ったクラスにアクセスして集計とかやるのがおもな目的になるのでTFormへのアクセスとかそこら辺のことはまったくやってません。
Pascal Script
Innerfuse Pascal Script と言われていたやつで、作者が RemObjects 社を作ってからは Pascal Script と言う名称になってます。無料です。
自前のクラスへのアクセスはちょっと面倒な感じがします。たぶん使うクラスを分離して付属のツール(PSUnitImporter.exe)でそのクラスの
※ここには載せてませんが、TestUnit.pas をインポーターにかけたら uPSI_TestUnit.pas が出来ます。リストの下にサンプルソースがあります。
FastScript かなり使いやすくて気に入ったんですが残念ながらトライアルです。実行するたびにダイアログボックスが開きます。また他の言語も使えます。
Pascal Script より 3-5 倍は早いです。またクラスへのアクセスは RTTI を使うことにより、少ない記述で済みます。
fsScript.AddClass(TData, 'TData');
だけで、クラスのプロパティーにアクセス出来ます。もちろん登録してやればメソッドにもアクセス可能です。
unit Main;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, System.DateUtils,
fs_iinterpreter, fs_ipascal, uPSComponent,
TestUnit,
uPSI_TestUnit, uPSComponent_Default;
type
TForm1 = class(TForm)
Memo1: TMemo;
Button1: TButton;
Button2: TButton;
ListBox: TListBox;
fsScript: TfsScript;
fsPascal1: TfsPascal;
PSScript: TPSScript;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure PSScriptCompile(Sender: TPSScript);
public
constructor Create (AOwner: TComponent); OVERRIDE;
function OutputFS (Instance: TObject; ClassType: TClass; const MethodName: string; var Params: variant) : variant;
procedure OutputPS (s: string);
function GetDataFS (Instance: TObject; ClassType: TClass; const MethodName: string; var Params: variant) : variant;
function GetDataPS : TData;
private
fData: TData;
end;
var Form1: TForm1;
implementation
{$R *.dfm}
constructor TForm1.Create(AOwner: TComponent);
var p: TPSPlugin;
begin
inherited Create(AOwner);
fData := TData.Create;
p := TPSImport_TestUnit.Create(Self);
TPSPluginItem(PSScript.Plugins.Add).Plugin := p;
end;
procedure TForm1.Button1Click(Sender: TObject);
var d: TData;
begin
fsScript.Clear;
fsScript.Lines.Text := Memo1.Text;
fsScript.Parent := fsGlobalUnit;
fsScript.AddMethod('procedure Log(s: String)', OutputFS);
fsScript.AddMethod('function GetData : TData', GetDataFS);
fsScript.AddClass(TData, 'TData');
if fsScript.Compile then begin
ListBox.Items.Add('=== FastScript ===');
fsScript.Execute;
ListBox.Items.Add(IntToStr(fData.Value));
end else begin
OutputPS(fsScript.ErrorMsg);
OutputPS(fsScript.ErrorPos);
end;
end;
procedure TForm1.Button2Click(Sender: TObject);
var a: integer;
d: TData;
begin
PSScript.Script.Text := Memo1.Text;
if PSScript.Compile then begin
ListBox.Items.Add('=== Pascal Script ===');
PSScript.Execute;
ListBox.Items.Add(IntToStr(fData.Value));
end else begin
for a := 0 to PSScript.CompilerMessageCount - 1 do
ListBox.Items.Add(PSScript.CompilerMessages[a].MessageToString);
end;
end;
procedure TForm1.PSScriptCompile(Sender: TPSScript);
begin
PSScript.AddMethod(Self, @TForm1.OutputPS, 'procedure Log(s: string);');
PSScript.AddMethod(Self, @TForm1.GetDataPS, 'function GetData : TData');
end;
function TForm1.OutputFS(Instance: TObject; ClassType: TClass; const MethodName: string; var Params: variant) : variant;
begin
OutputPS(Params[0]);
end;
procedure TForm1.OutputPS(s: string);
begin
ListBox.Items.Add(s + Format(' (%.1f)', [GetTickCount / 1000]));
end;
function TForm1.GetDataFS(Instance: TObject; ClassType: TClass; const MethodName: string; var Params: variant) : variant;
begin
GetDataFS := NativeInt(fData);
end;
function TForm1.GetDataPS : TData;
begin
GetDataPS := fData;
end;
end.
サンプルプロジェクト: ダウンロード※コンパイルには FastScript と Pascal Script が必要。実行ファイル付。
p.s.
FastScript の構文をハイライトで表示してくれるメモコントロールの TfsSyntaxMemo はまったく日本語に対応してませんでした。まぁ別にかまわんけど...

0 件のコメント:
コメントを投稿