delphi – DWScript:传递set-of-enumerated -type将传递一个整
在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,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],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.这样可以很好地工作并解决上面的所有情况,否则会失败. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |