简体   繁体   English

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

[英]DWScript: passing a set-of-enumerated-type will pass an array of integer

From a DWScript script, I call a method of an object instance exposed by the Delphi side. 在DWScript脚本中,我调用Delphi端公开的对象实例的方法。 The method takes, among others, an argument which is a set of some enumerated data type. 该方法除其他外采用一个参数,该参数是一组枚举数据类型。 This enumerated datatype is exposed from Delphi to the script. 此枚举数据类型从Delphi公开到脚本。

I saw from the error message generated at script compile time that DWScript pass such an argument as an array of integer and that the Delphi side receive an array of variant (TData). 我从脚本编译时生成的错误消息中看到,DWScript将这样的参数作为整数数组传递,并且Delphi端接收变量数组(TData)。

I had to write a wrapper at Delphi side which loops thru the array and rebuild the corresponding set-of variable to pass it to the actual Delphi function. 我必须在Delphi端编写一个包装器,它通过数组循环并重建相应的变量集以将其传递给实际的Delphi函数。 Accessing the array is done using "ProgramInfo.Vars['MsgFlags'].GetData". 使用“ProgramInfo.Vars ['MsgFlags']。GetData”访问数组。

This works perfectly well, but is this the correct may to do? 这非常有效,但这是正确的可能吗? Did I miss something? 我错过了什么?

Script side code: 脚本边码:

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

Delphi side code: 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;

I would implement the Delphi side a bit differently (see below), but apart from that your solution appears correct. 我会稍微改变Delphi方面(见下文),但除此之外你的解决方案看起来是正确的。


The quirk, as you've correctly observed, is that DWScript represents static sets as arrays. 正如您所正确观察到的那样,这个怪癖是DWScript将静态集表示为数组。 Note however that this is just a limitation of the compiler frontend which hopefully, someday, will be resolved. 但请注意,这只是编译器前端的限制,希望有一天能够解决。 See DWScript issue #10: Improve implicit casts from static arrays to sets . 请参阅DWScript问题#10:改进从静态数组到集的隐式转换

The following script demonstrates in which cases the compiler performs an implicit cast between set and array: 以下脚本演示了编译器在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;

The above is purely a script side implementation. 以上纯粹是脚本端实现。 When you add a Delphi side implementation into the mix it can get problematic. 当您在混合中添加Delphi端实现时,它可能会出现问题。

Consider a simplified implementation of the MessageDlg function: 考虑MessageDlg函数的简化实现:

Delphi side declaration (via TdwsUnit): Delphi边声明(通过TdwsUnit):

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

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

Delphi side implementation: Delphi端实现:

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

Script side usage: 脚本用法:

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;

Now lets try the same with your solution declaring the set parameter as an array instead: 现在让我们尝试使用您的解决方案,将set参数声明为数组:

Delphi side declaration (via TdwsUnit): Delphi边声明(通过TdwsUnit):

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

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

Delphi side implementation: 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;

Script side usage: 脚本用法:

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

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

In my own branch of DWScript I've modified the compiler to perform an implicit cast from an array of enum values to a set: DWScript pull request #4: Enhancement to set type . 在我自己的DWScript分支中,我修改了编译器以执行从枚举值数组到集合的隐式转换: DWScript拉取请求#4:增强设置类型 This works beautifully and resolves all the cases above that otherwise fail. 这样可以很好地解决上述所有情况,否则会失败。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM