DWScript: passing a set of an enumerated type will pass an array of integers

From a DWScript script, I call the object instance method opened by the Delphi side. The method takes, among other things, an argument, which is a collection of some of the data types listed. This enumerated data type is opened from Delphi in a script.

I saw from the error message generated in the compile time script that DWScript passes such an argument as an array of integers and that the Delphi side receives an array of options (TData).

I had to write a wrapper on the Delphi side that traverses the array and rebuilds the corresponding variable to pass it to the actual Delphi function. The array is accessed using "ProgramInfo.Vars ['MsgFlags"]. GetData ".

This works fine, but is it right to do it? Did I miss something?

Script side code:

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

Delphi side code:

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;
+4
source share
1 answer

I would implement the Delphi side several times (see below), but also, your solution looks right.


The habit, as you rightly noted, is that DWScript is a static set in the form of arrays. Please note, however, that this is just a limitation of the compiler interface, which I hope will someday be resolved. See Problem with DWScript # 10: Improve Implicit Casts from Static Arrays to Collections .

The following script demonstrates when the compiler performs implicit casting between a set and an 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;

script. 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);

Script :

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;

Script :

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 # 4: . , .

+3

Source: https://habr.com/ru/post/1612888/


All Articles