使用RemObjects Pascal Script
摘自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还包含几个函数库:
|
允许脚本使用DLL中的导出函数,语法: |
|
导入Tobject和Classes单元. |
|
导入date/time相关函数. |
|
在脚本中可使用COM对象. |
|
导入db.pas. |
|
导入Forms及Menus单元. |
|
导入Controls.pas和Graphics.pas单元. |
|
导入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的更多相关文章
- 使用RemObjects Pascal Script (转)
http://www.cnblogs.com/MaxWoods/p/3304954.html 摘自RemObjects Wiki 本文提供RemObjects Pascal Script的整体概要并演 ...
- 在delphi中嵌入脚本语言--(译)RemObjects Pascal Script使用说明(1)(译)
翻譯這篇文章源於我的一個通用工資計算平台的想法,在工資的計算中,不可避免的需要使用到自定義公式,然而對於自定義公式的實現,我自己想了一些,也在網上搜索了很多,解決辦法大致有以下幾種: 1. 自己寫代碼 ...
- 测试RemObjects Pascal Script
unit Unit1; interface usesWindows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, ...
- Inno Setup Pascal Script to search for running process
I am currently trying to do a validation at the uninstall moment. In a Pascal script function, in In ...
- Pascal Script
MsgBox http://www.jrsoftware.org/ishelp/index.php?topic=isxfunc_msgbox ExpandConstant http://www.jrs ...
- delphi一些小技巧 从别处看到
开发环境-------- Delphi 7是一个很经典的版本,在Win2000/XP下推荐安装Delphi 7来开发软件,在Vista下推荐使用Delphi 2007开发软件.安装好Delphi ...
- (转载)Delphi开发经验谈
Delphi开发经验谈 开发环境-------- Delphi 7是一个很经典的版本,在Win2000/XP下推荐安装Delphi 7来开发软件,在Vista下推荐使用Delphi 2007开发软件. ...
- Pascal编译器大全(非常难得)
http://www.pascaland.org/pascall.htm Some titles (french) : Compilateurs Pascal avec sources = compi ...
- Delphi 控件大全
delphi 控件大全(确实很全) delphi 控件查询:http://www.torry.net/ http://www.jrsoftware.org Tb97 最有名的工具条(ToolBar ...
随机推荐
- C语言清空输入缓冲区的N种方法对比【转】
转自:http://www.cnblogs.com/codingmylife/archive/2010/04/18/1714954.html C语言中有几个基本输入函数: //获取字符系列 int f ...
- 关于RestFul API 介绍与实践
之前演示的PPT,直接看图... •参考链接: •RESTful API 设计最佳实践 •RESTful API 设计指南 •SOAPwebserivce和RESTfulwebservice对 ...
- 几种list排序方法
package com.lgx.jdk8.part02; import java.util.*; import java.util.stream.Collectors; /** * Comparato ...
- jenkins的svn路径中文问题
今天弄Jenkins,我们的SVN代码路径是中文的,他娘的坑死我了,很没面子弄了俩点,网上方案试了好多,说装插件,修改Tomcat server.xml,基本没用,后来看到一个帖子写的方案蛮实用的,分 ...
- Excel学习笔记:vlookup基础及多条件查找
一.vlookup基础 关于vlookup的基础不多记录,相信基本的使用方法大家都懂得. 使用格式:=vlookup(搜索值,搜索范围,列号,是否精准匹配) =VLOOKUP(E2,$B$2:$C$6 ...
- Angular 5项目
Angular 5项目 如果您正在使用angular, 但是没有好好利用angular cli的话, 那么可以看看本文. Angular CLI 官网: https://github.com/angu ...
- Codeforces-1077C
title: Codeforces-1077C date: 2018-11-24 15:22:31 tags: acm 刷题 categories: Codeforces 题意 题目链接 给你一个数组 ...
- 用Thread类创建线程
在Java中创建线程有两种方法:使用Thread类和使用Runnable接口.在使用Runnable接口时需要建立一个Thread实例.因此,无论是通过Thread类还是Runnable接口建立线程, ...
- Lambda的分类(语句Lambda和表达式Lambda)
学习自 <C#本质论> Overview 在上一文中,我们简而又简的了解了一下,匿名方法和Lambda表达式,关于匿名方法这里暂且不表,本文我们来更加详细的了解一下Lambda表达式. 本 ...
- require和require.async的区别
本文用seajs来讲解两种模块加载方式require和require.async的区别,类似java里的import,php里的include. <!DOCTYPE html> <h ...