В этой статье я хочу рассказать о замечательном компоненте для Delphi RemObjects PascalScript. Суть этого компонента в том, что вы можете писать скрипты, синтаксически подобные языку Pascal и выполнять их. Движок исполнения скриптов легко встраивается в вашу программу и может позволить расширить функциональность вашего проекта возможностями встроенного скриптового языка. Иногда подобная функциональность просто незаменима и позволяет не изобретать велосипед написанием собственного компилятора или интерпретатора.
RemObjects PascalScript является бесплатным компонентом и поставляется в исходных кодах, хорошо отлажен и практически безглючен. Скачать его можно по этой
ссылке.
В поставке PascalScript идет несколько компонентов, а также множество примеров, изучив которые можно сделать то, что вам нужно в вашем проекте. Поэтому подробно останавливаться на основах PascalScript мы не будем, но остановимся на следующих аспектах:
- Вызов из скриптов процедур и функций, подготовленных вами заранее
- Вызов свойств и методов ваших классов
Фактически, эти возможности являются наиболее ценными, иначе простое исполнение стандартных программных конструкций вряд ли сможет принести вам значительную пользу. Ведь главное в скриптовых движках - дать пользователю возможность писать небольшие программные конструкции, гибко расширяющие функциональность вашей системы и способные использовать заранее подготовленные мощные функции, а также экземпляры классов и их методы.
Тестовый проект
Создадим простой тестовый проект для демонстрации возможностей RemObjects PascalScript. На форму проекта поместим два TMemo (текст скрипта и сообщение результатов компиляции), одну кнопку для компиляции скрипта и сам компонент TPSScript (который присутствует в Tool Palette после установки PascalScript)
Форма проекта будет выглядеть примерно так:
Код компиляции, связанный с кнопкой Compile будет такой:
procedure TForm1.CompileClick(Sender: TObject);
var i: integer;
begin
PSScript1.Script.Text:=Memo1.Text;
if PSScript1.Compile then
begin
Memo2.Text:='No errors';
PSScript1.Execute;
end else
begin
Memo2.Lines.Clear;
for i := 0 to PSScript1.CompilerMessageCount -1 do
Memo2.Lines.Add(PSScript1.CompilerMessages[i].MessageToString);
end;
end;
Тестовый код успешно компилируется. Про тонкости встроенной в PascalScript функциональности смотрите примеры, поставляемые вместе с компонентом, нас же будут интересовать вопросы, озвученные в начале статьи.
Вызов внешней функции
Одна из наиболее востребованных и интересных возможностей. Напишем простейшую функцию:
function TForm1.TestMessage(AText: string): boolean;
begin
ShowMessage(AText);
Result:=true;
end;
Теперь ее надо сделать доступной в PascalScript. Для этого в событие onCompile компонента PSScript1 добавим следующий код:
Sender.AddMethod(Self, @TForm1.TestMessage,'function TestMessage(AText: string): boolean;');
Теперь можно выполнить такой скрипт:
begin
TestMessage('Test message...');
end;
Выполнив этот скрипт, мы получим окно с переданным в функцию сообщением.
Вызов методов и свойств существующего экземпляра класса
Добавим в uses следующие модули:
uses ... , uPSRuntime, uPSCompiler;
Напишем простейший класс:
TTestClass=class
public
data: string;
procedure ShowMsg(AText: string);
end;
...
procedure TTestClass.ShowMsg(AText: string);
begin
ShowMessage(AText);
end;
В форме Form1 создадим экземпляр нашего класса:
TestClass: TTestClass;
...
procedure TForm1.FormCreate(Sender: TObject);
begin
TestClass:=TTestClass.Create;
end;
Теперь нам надо сделать экземпляр этого класса и его метод ShowMsg и свойство data видимым в PascalScript. Для этого добавим код импорта класса, его свойств и методов, а также код регистрации класса в соответствующие обработчики событий.
Код импорта класса для компилятора:
procedure TForm1.PSScript1CompImport(Sender: TObject; x: TPSPascalCompiler);
begin
with x.AddClassN(x.FindClass('TOBJECT'),'TTestClass') do
begin
RegisterProperty('data', 'string', iptrw);
RegisterMethod('Procedure ShowMsg( AText : string)');
end;
end;
Код импорта класса для Runtime:
procedure TForm1.PSScript1ExecImport(Sender: TObject; se: TPSExec; x: TPSRuntimeClassImporter);
procedure TTestClass_data_W(Self: TTestClass; const T: string);
begin
Self.data := T;
end;
procedure TTestClass_data_R(Self: TTestClass; var T: string);
begin
T := Self.data;
end;
begin
with x.Add(TTestClass) do
begin
RegisterPropertyHelper(@TTestClass_data_R,@TTestClass_data_W,'data');
RegisterMethod(@TTestClass.ShowMsg, 'ShowMsg');
end;
end;
Код регистрации класса для компилятора:
procedure TForm1.PSScript1Compile(Sender: TPSScript);
begin
Sender.AddRegisteredPTRVariable('TestClass', 'TTestClass');
end;
Код регистрации экземпляра класса для Runtime:
procedure TForm1.PSScript1Execute(Sender: TPSScript);
begin
PSScript1.SetPointerToData('TestClass', @FTestClass, PSScript1.FindNamedType('TTestClass'));
end;
Все, теперь можно использовать свойства и методы экземпляра класса непосредственно в скриптах. Например:
begin
TestClass.Data:='Test Message';
TestClass.ShowMsg(TestClass.Data);
end.
Код не требует подробного комментария, его использование вполне понятно при вдумчивом изучении тестового примера.
Смотрите также:
Оставьте свой комментарий
Вы должны быть авторизированны, чтобы оставить комментарий.