Использование RemObjects Pascal Script (Эта статья является моим вольным переводом статьи PS01 - Using the RemObjects Pascal Script с сайта RemObjects Software. Внесены незначительные исправления в текст и добавлены примеры - Снег Север). В этой статье сделан обзор пакета компонентов RemObjects Pascal Script и объясняется, как сделать и исполнить некоторые простые скрипты. Концептуально Pascal Script состоит из двух различных частей:
Эти две части независимы друг от друга. Вы можете использовать их непосредственно или использовать компонент TPSScript, который находится в модуле uPSComponent.pas и объединяет их в одном удобном для применения классе. Для применения компонентной версии Pascal Script вы должны поместить его на вашу форму или модуль баз данных, настроить (назначить) свойство 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; (sample00)
По умолчанию компонент добавляет только несколько стандартных функций к скриптовому движку (их перечень можно увидеть в начале модуля uPSComponents.pas). В дополнение к стандартным функциям, имеется несколько библиотек, включенных в Pascal Script:
Для использования этих библиотек, положите их на форму (модуль баз данных), в свойстве Plugins компонента TPSCompiler нажмите кнопку [...], добавьте новый элемент и назначьте свойство Plugin соответствующему компоненту. В дополнение к стандартным библиотекам вы можете легко добавлять новую функциональность к скриптовому движку. Для этого создайте новый метод, который вы желаете добавить к скриптовому движку, например:
Затем назначьте обработчик для события OnCompile event и используйте метод AddMethod компонента TPSCompiler чтобы добавить новый метод:
Пример скрипта, который использует эту функцию, может выглядеть так:
(sample01)
Расширенная функциональность Pascal Script включает в себя препроцессор, который позволяет вам использовать команды препроцессора (defines) ({$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; (sample02) Когда эти свойства установлены, свойство-массив CompilerMessages будет включать имя файла, в котором эти сообщения инициируются.
Дополнительно вы можете вызывать скриптовые функции в Delphi. Следующий пример используется как скрипт: function TestFunction(Param1: Double; Data: String): Longint; begin ShowNewMessage('Param1: '+FloatToStr(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)))); (sample03)
Можно также добавлять переменные в скриптовый движок и затем использовать их в скриптах. Для этого необходимо применить функцию AddRegisteredVariable. Это можно сделать в событии OnCompile: procedure TForm1.CECompile(Sender: TPSScript); begin ce.AddRegisteredVariable('MYVAR', 'Longint'); end; Значение этой переменной можно дать в событии OnExecute: procedure TForm1.ceExecute(Sender: TPSScript); begin VSetInt(CE.GetVariable('MYVAR'), 1234567); end;
Для того, чтобы узнать значение этой переменной после выполнения скрипта, вы можете использовать событие OnAfterExecute: VGetInt(CE.GetVariable('MYVAR')) Можно также зарегистрировать внешние переменные для скрипта. Этот процесс состоит из двух шагов – во-первых, в событии OnCompile добавляются переменные и их типы с помощь функции AddRegisteredPTRVariable. procedure TMyForm.CECompile(Sender: TPSScript); begin Sender.AddRegisteredPTRVariable('Memo2', 'TMemo'); Sender.AddRegisteredPTRVariable('MyVar1', 'Longint'); end; Это зарегистрирует переменные MyClass и MyVar. Во-вторых, назначим ссылки на эти переменные в событии OnExecute: procedure TMyForm.CEExecute(Sender: TPSScript); begin CE.SetPointerToData('MyVar1', @MyVar1, CE.FindBaseType(bts32)); CE.SetPointerToData('Memo2', @Memo2, CE.FindNamedType('TMemo')); end; Вам также надо добавить и зарегистрировать в компиляторе компоненты TPSImport_Classes, TPSImport_Controls и TPSImport_StdCtrls. (sample04)
В Pascal Script есть два вида типов переменных – базовые типы, которые являются простыми типами (см. Таблицу ниже) и классовые типы. Базовые типы регистрируются модулем uPSUtils.pas и могут быть найдены с помощью функции FindBaseType. Классовые типы находят по имени, используя FindNamedType. Изменения в этих переменных непосредственно изменяет актуальную переменную. Базовые типы:
Компонентная версия Pascal Script также поддерживает выполнение скриптовых функций. Это делается с помощью метода ExecuteFunction. ShowMessage(CE.ExecuteFunction([1234.5678, 4321, 'test'], 'TestFunction')); Это выполнит функцию с именем 'TestFunction' с 3-мя параметрами - float, integer и string. Результат будет отправлен обратно в ShowMessage. (sample05) Замечания:
|