当前位置 : 主页 > 编程语言 > delphi >

delphi – DWScript:传递set-of-enumerated -type将传递一个整数数组

来源:互联网 收集:自由互联 发布时间:2021-06-23
在DWScript脚本中,我调用Delphi端公开的对象实例的方法.该方法除其他外采用一个参数,该参数是一组枚举数据类型.此枚举数据类型从Delphi公开到脚本. 我从脚本编译时生成的错误消息中看
在DWScript脚本中,我调用Delphi端公开的对象实例的方法.该方法除其他外采用一个参数,该参数是一组枚举数据类型.此枚举数据类型从Delphi公开到脚本.

我从脚本编译时生成的错误消息中看到,DWScript将这样的参数作为整数数组传递,并且Delphi端接收变量数组(TData).

我必须在Delphi端编写一个包装器,它通过数组循环并重建相应的变量集以将其传递给实际的Delphi函数.使用“ProgramInfo.Vars [‘MsgFlags’].GetData”访问数组.

这非常有效,但这是正确的可能吗?我错过了什么?

脚本边码:

procedure Test;
begin
    DelphiObject.Demo('Hello', [mffStop, mffClose]);
end;

Delphi边码:

TFlag  = (mmfStop, mffStart, mmfClose);
TFlags = set of TFlag;

// Internal method doing the actual job
procedure TDelphiObject.DemoInternal(
    const MsgText  : String;
    const MsgFlags : TFlags);
begin
    // Some code...
end;

// Wrapper method exposed to script
procedure TDelphiObject.Demo(
    const MsgText : String;
    const MsgFlags : array of integer);
var
    Flags      : TFlags;
    I          : Integer;
begin
    Flags := [];
    for I := Low(MsgFlags) to High(MsgFlags) do
        Flags := Flags + [TFlag(MsgFlags[I])];
    DemoInternal(MsgText, Flags);
end;
我会稍微改变Delphi方面(见下文),但除此之外你的解决方案看起来是正确的.

正如您所正确观察到的那样,这个怪癖是DWScript将静态集表示为数组.但请注意,这只是编译器前端的限制,希望有一天能够解决.见DWScript issue #10: Improve implicit casts from static arrays to sets.

以下脚本演示了编译器在set和array之间执行隐式转换的情况:

type
  TMyEnum = (meOne, meTwo);
type
  TMySet = set of TMyEnum;
type
  TMyArray = array of TMyEnum;

procedure TestSet(MySet: TMySet);
begin
  ShowMessage(integer(MySet).toString);
end;

procedure TestArray(MyArray: TMyArray);
var
  MySet: TMySet;
begin
  MySet := [];
  for var i := 0 to MyArray.Length-1 do
    Include(MySet, MyArray[i]);
  ShowMessage(integer(MySet).toString);
end;

begin
  TestSet([]);
  TestArray([]);
  TestSet([meOne]);
  TestArray([meOne]);
  TestSet([meOne, meTwo]);
  TestArray([meOne, meTwo]);

  var VarSet: TMySet = [meOne, meTwo];
  TestSet(VarSet);
  // Syntax Error: Argument 0 expects type "array of TMyEnum" instead of "TMySet"
  // TestArray(VarSet);

  var VarArray: TMyArray = [meOne, meTwo];
  TestArray(VarArray);
  // Syntax Error: Argument 0 expects type "array of TMyEnum" instead of "TMySet"
  // TestArray(VarSet);

  // Syntax Error: Incompatible types: "TMySet" and "array [0..1] of TMyEnum"  const ConstSet: TMySet = [meOne, meTwo];
  // const ConstSet: TMySet = [meOne, meTwo];
  // TestSet(ConstSet);
  // TestArray(ConstSet);

  // Syntax Error: Incompatible types: "array of TMyEnum" and "array [0..1] of TMyEnum"
  // const ConstArray: TMyArray = [meOne, meTwo];
  // TestSet(ConstArray);
  // TestArray(ConstArray);
end;

以上纯粹是脚本端实现.当您在混合中添加Delphi端实现时,它可能会出现问题.

考虑MessageDlg函数的简化实现:

Delphi边声明(通过TdwsUnit):

type
  TMsgDlgBtn = (mbYes, mbNo, mbOK, mbCancel, etc...);
  TMsgDlgButtons = set of TMsgDlgBtn;

function MessageDlg(const Msg: string; Buttons: TMsgDlgButtons): integer;

Delphi端实现:

Info.ResultAsInteger := MessageDlg(Info.ParamAsString[0], mtInformation, TMsgDlgButtons(Word(Info.ParamAsInteger[1])), -1);

脚本用法:

begin
  // Implicit cast from array to set fails:
  // Syntax Error: There is no overloaded version of "MessageDlg" that can be called with these arguments
  // MessageDlg('Test', [mbOK]);

  var Buttons: TMsgDlgButtons = [mbOK];
  MessageDlg('Test', Buttons);
end;

现在让我们尝试使用您的解决方案,将set参数声明为数组:

Delphi边声明(通过TdwsUnit):

type
  TMsgDlgBtn = (mbYes, mbNo, mbOK, mbCancel, etc...);
  TMsgDlgButtons = array of TMsgDlgBtn;

function MessageDlg(const Msg: string; Buttons: TMsgDlgButtons): integer;

Delphi端实现:

var
  Buttons: TMsgDlgButtons;
  i: integer;
  ButtonArray: IScriptDynArray;
begin
  ButtonArray := Info.Params[1].ScriptDynArray;
  Buttons := [];
  for i := 0 to ButtonArray.ArrayLength-1 do
    Include(Buttons, TMsgDlgBtn(ButtonArray.AsInteger[i]));
  Info.ResultAsInteger := MessageDlgEx(Info.ParamAsString[0], mtInformation, Buttons, -1);
end;

脚本用法:

begin
  MessageDlg('Test', [mbOK]);

  var Buttons: TMsgDlgButtons = [mbOK];
  // Note that an implicit cast from set to array is performed
  MessageDlg('Test', Buttons);
end;

在我自己的DWScript分支中,我修改了编译器以执行从枚举值数组到集合的隐式强制转换:DWScript pull request #4: Enhancement to set type.这样可以很好地工作并解决上面的所有情况,否则会失败.

网友评论