標籤:byte ssm 常量 tom ica pex path 進階特性 addm
http://www.cnblogs.com/MaxWoods/p/3304954.html
摘自RemObjects Wiki
本文提供RemObjects Pascal Script的整體概要並示範如何建立一些簡單的指令碼.
Pascal Script包括兩個不同部分:
- 編譯器 (uPSCompiler.pas)
- 運行時 (uPSRuntime.pas)
兩部分彼此獨立.可以分開使用,或通過TPSScript 控制項使用他們,這個控制項定義在uPSComponent.pas單元,對這兩個部分進行簡易封裝.
要使用控制項版本的Pascal Script,首先要將控制項放在表單或data module上,並設定script屬性,調用Compile和Execute方法.編譯的錯誤,警告,提示可在CompilerMessages數組屬性中擷取,同樣執行階段錯誤儲存在ExecErrorToString屬性中.
下面的範例將編譯並執行一個空指令碼("begin end."):
var
Messages: string;
compiled: boolean;
begin
ce.Script.Text := ‘begin end.‘;
Compiled := Ce.Compile;
for i := 0 to ce.CompilerMessageCount -1 do
Messages := Messages +
ce.CompilerMessages[i].MessageToString +
#13#10;
if Compiled then
Messages := Messages + ‘Succesfully compiled‘#13#10;
ShowMessage(‘Compiled Script: ‘#13#10+Messages);
if Compiled then begin
if Ce.Execute then
ShowMessage(‘Succesfully Executed‘)
else
ShowMessage(‘Error while executing script: ‘+
Ce.ExecErrorToString);
end;
end;
預設情況下,控制項只向指令碼引擎添加少數幾個標準函數(具體函數可從uPSComponents.pas單元頂部擷取).
除了標準函數,Pascal Script還包含幾個函數庫:
TPSDllPlugin |
允許指令碼使用DLL中的匯出函數,文法: function FindWindow(C1, C2: PChar): Longint; external‘[email protected] stdcall‘; |
TPSImport_Classes |
匯入Tobject和Classes單元. |
TPSImport_DateUtils |
匯入date/time相關函數. |
TPSImport_ComObj |
在指令碼中可使用COM對象. |
TPSImport_DB |
匯入db.pas. |
TPSImport_Forms |
匯入Forms及Menus單元. |
TPSImport_Controls |
匯入Controls.pas和Graphics.pas單元. |
TPSImport_StdCtrls |
匯入ExtCtrls和Buttons. |
要使用這些庫,將相應控制項添加到表單或Data Module中,選擇TPSCompiler控制項點擊plugins屬性後的[...]按鈕,增加一個新項並設定其Plugin屬性為特定的外掛程式控制項.除了這些標準庫函數,還可以輕鬆的向指令碼引擎添加新函數.為了實現這個目的,首先建立要匯出給指令碼引擎的函數,例如:
procedure TForm1.ShowNewMessage(const Message: string);
begin
ShowMessage(‘ShowNewMessage invoked:‘#13#10+Message);
end;
然後,實現TPSCompile控制項的OnCompile事件,使用AddMethod方法註冊實際方法:
procedure TForm1.CECompile(Sender: TPSScript);
begin
Sender.AddMethod(Self, @TForm1.ShowNewMessage,
‘procedure ShowNewMessage
(const Message: string);‘);
end;
在指令碼中調用方式:
begin
ShowNewMessage(‘Show This !‘);
end.
進階特性
Pascal指令碼支援先行編譯,可以使用{$IFDEF}, {$ELSE}, {$ENDIF}指令,而且可以使用{$I filename.inc}指令將其他檔案內容引入指令碼中.為了使用這個特性,必須設定UsePreprocessor屬性為True,而且MainFileName屬性必須與Script屬性中的指令碼名稱相匹配.Defines屬性指定預定義指令,在OnNeedFile事件中處理引入其他檔案.
function TForm1.ceNeedFile(Sender: TObject;
const OrginFileName: String;
var FileName, Output: String): Boolean;
var
path: string;
f: TFileStream;
begin
Path := ExtractFilePath(ParamStr(0)) + FileName;
try
F := TFileStream.Create(Path, fmOpenRead or fmShareDenyWrite);
except
Result := false;
exit;
end;
try
SetLength(Output, f.Size);
f.Read(Output[1], Length(Output));
finally
f.Free;
end;
Result := True;
end;
當設定了這些屬性,CompilerMessages數組屬性將輸出包含檔案的名稱.
另外,你可以在Delphi中呼叫指令碼中的函數.下面的代碼定義在指令碼中:
function TestFunction(Param1: Double; Data: String): Longint;
begin
ShowNewMessage(‘Param1: ‘+FloatToString(param1)
+#13#10+‘Data: ‘+Data);
Result := 1234567;
end;
begin
end.
在使用指令碼中的函數之前,必須檢查函數參數與傳回值類型,可在OnVerifyProc事件中進行.
procedure TForm1.CEVerifyProc(Sender: TPSScript;
Proc: TPSInternalProcedure;
const Decl: String;
var Error: Boolean);
begin
if Proc.Name = ‘TESTFUNCTION‘ then begin
if not ExportCheck(Sender.Comp, Proc,
[btS32, btDouble, btString], [pmIn, pmIn]) then begin
Sender.Comp.MakeError(‘‘, ecCustomError, ‘Function header for
TestFunction does not match.‘);
Error := True;
end
else begin
Error := False;
end;
end
else
Error := False;
end;
ExportCheck函數檢查參數是否匹配.本例中,btu8是boolean (傳回值類型), btdouble是第一個參數, btString是第二個參數.[pmIn, pmIn]指示兩個參數都是IN參數.要調用這個指令碼函數還需要為這個函數建立一個事件聲明.
type
TTestFunction = function (Param1: Double;
Data: String): Longint of object;
//...
var
Meth: TTestFunction;
Meth := TTestFunction(ce.GetProcMethod(‘TESTFUNCTION‘));
if @Meth = nil then
raise Exception.Create(‘Unable to call TestFunction‘);
ShowMessage(‘Result: ‘+IntToStr(Meth(pi, DateTimeToStr(Now))));
也可以向指令碼引擎中添加變數,使之可在指令碼中使用.可在OnExecute事件中調用AddRegisteredVariable函數實現:
procedure TForm1.ceExecute(Sender: TPSScript);
begin
CE.SetVarToInstance(‘SELF‘, Self);
// ^^^ For class variables
VSetInt(CE.GetVariable(‘MYVAR‘), 1234567);
end;
在指令碼執行完畢後,讀取變數的新值,可在OnAfterExecute事件中調用: VGetInt(CE.GetVariable(‘MYVAR‘)).
向指令碼引擎註冊外部變數,有兩個步驟,首先在OnCompile事件中,使用AddRegisteredPTRVariable函數向指令碼中添加變數聲明.
procedure TMyForm.PSScriptCompile(Sender: TPSScript);
begin
Sender.AddRegisteredPTRVariable(‘MyClass‘, ‘TButton‘);
Sender.AddRegisteredPTRVariable(‘MyVar‘, ‘Longint‘);
end;
這就將外部變數MyClass和MyVar匯入了.其次,在OnExecute事件中將變數與具體指標關聯:
procedure TMyForm.PSScriptExecute(Sender: TPSScript);
begin
PSScript.SetPointerToData(‘MyVar‘, @MyVar, PSScript.FindBaseType(bts32));
PSScript.SetPointerToData(‘Memo1‘, @Memo1, PSScript.FindNamedType(‘TMemo‘));
end;
這裡在指令碼中有兩種類型變數,基礎類型(如下表的簡單類型),及類類型.基礎類型定義在uPSUtils.pas單元,可使用FindBaseType函數擷取.類類型使用FindNamedType按名稱擷取.在指令碼中修改變數將直接影響關聯的變數.
基礎類型:
btU8 |
Byte |
btS8 |
Shortint |
btU16 |
Word |
btS16 |
Smallint |
btU32 |
Longword |
btS32 |
Longint |
btS64 |
Int64 |
btSingle |
Single |
btDouble |
Double |
btExtended |
Extended |
btVariant |
Variant |
btString |
String |
btWideString |
WideString |
btChar |
Char |
btWideChar |
WideChar |
基於控制項的Pascal指令碼也可執行指令碼函數.需要使用ExecuteFunction方法.
ShowMessage(CompExec.ExecuteFunction([1234.5678, 4321,
‘test‘],
‘TestFunction‘));
這將執行叫做‘TestFunction‘的函數,有三個參數,一個float類型,一個integer類型和一個string類型.傳回值直接傳給ShowMessage.
注意:
- 為使用一些函數和常量,有必要將uPSCompiler.pas, uPSRuntime.pas和uPSUtils.pas引入到uses中.
- 指令碼引擎不會主動調用Application.ProcessMessages,導致指令碼運行時應用程式掛起.為了避免這個問題,可在TPSScript.OnLine事件中調用Application.ProcessMessages.
- 如果要向指令碼引擎匯入自訂的類,可以使用/Unit-Importing/目錄下的工具產生匯入類庫.
- 如果要向指令碼指令碼引擎匯入自訂類,可使用Bin目錄下的工具產生匯入類庫.
- 如果分開使用compiler和runtime,請見Import和Kylix範例.
- Debug範例需要控制項SynEdit http://synedit.sourceforge.net.
Retrieved from "http://wiki.remobjects.com/wiki/Using_RemObjects_Pascal_Script"
使用RemObjects Pascal Script (轉)