Is it possible to call Delphi method with variable number of arguments from IActiveScript?

I'm using Delphi 2006 and psvActiveScript.

Example:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, 
  ObjComAuto, ComObj, psvActiveScript;

type
  TForm1 = class(TForm)
    btnExecute: TButton;
    procedure btnExecuteClick(Sender: TObject);
    procedure ASWError(Sender: TObject; Line, Pos: Integer; ASrc, ADescription: String);
  end;

var
  Form1: TForm1;
  ASW: TpsvActiveScriptWindow;

implementation

{$R *.DFM}

type
  {$METHODINFO ON}
  TMySriptableClass = class(TObjectDispatch)
  public
    constructor Create;
    procedure Alert(msg: string);
    // THIS OR SOMETHING SIMILAR NOT POSSIBLE? **********************
    function FnWithVarNumOfArgs(const args: array of string): string;
    // **************************************************************
  end;
  {$METHODINFO OFF}

constructor TMySriptableClass.Create;
begin inherited Create(Self, False); end;

procedure TMySriptableClass.Alert(msg: string);
begin ShowMessage(msg); end;

function TMySriptableClass.FnWithVarNumOfArgs(const args: array of string): string;
begin Result := 'OK'; end;


procedure TForm1.btnExecuteClick(Sender: TObject);
var
  MyObj: TMySriptableClass;
begin
  ASW := TpsvActiveScriptWindow.Create(self);
  ASW.ScriptLanguage := 'JScript';
  ASW.OnError := ASWError;

  MyObj := TMySriptableClass.Create;
  ASW.AddNamedItem('MyObj', MyObj);

  try
    ASW.Execute(
      'MyObj.Alert("Warning: Here comes Error");'+
      'MyObj.FnWithVarNumOfArgs("1","2","3")'
    );
  finally
    ASW.Free;
  end;
end;

procedure TForm1.ASWError(Sender: TObject; Line, Pos: Integer; ASrc, ADescription: String);
begin Showmessage(ADescription + ': ' + ASrc); end;

end.

Answers:

Answer
[...]
uses
  activex, objcomauto, comobj;

type
  {$METHODINFO ON}
  TMySriptableClass = class(TObjectDispatch)
  public
    [...]
    function FnWithVarNumOfArgs(const args: OleVariant): string;
    [...]


function TMySriptableClass.FnWithVarNumOfArgs(const args: OleVariant): string;
var
  dispParams: activex.DISPPARAMS;
  vtRet, Element: OleVariant;
  Enum: IEnumVARIANT;
  Fetched: LongWord;
begin
  if TVarData(args).VType = varDispatch then begin
    OleCheck(IDispatch(args).Invoke(DISPID_NEWENUM, GUID_NULL,
                                    LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET,
                                    dispParams, @vtRet, nil, nil));
    Enum := IUnknown(vtRet) as IEnumVARIANT;
    while (Enum.Next(1, Element, Fetched) = S_OK) do
      ShowMessage(Element);
  end;

  Result := 'OK';
end;


    [...]
    ASW.Execute('var myArray=["myarg1", 5, true];' +
                'MyObj.FnWithVarNumOfArgs(myArray);');
    [...]
Answer

The way you have set it up now, you would need to pass in an array of string since you declared the parameter as such. In Delphi itself that could be done using

MyObj.FnWithVarNumOfArgs(Array("1","2","3"))

Which would create a dynamic arry with the given values and then pass it to FnWithVarNumOfArgs.

From a scripting language Delphi's Array function certainly won't be available and you would need to do something clever with pointers, and I have no clue whether you could even get that to work.

Possibly your best bet is to use what is known as Variant Open Array Parameters.

From the help: http://docwiki.embarcadero.com/RADStudio/en/Parameters_(Delphi)#Variant_Open_Array_Parameters

Variant open array parameters allow you to pass an array of differently typed expressions to a single procedure or function. To define a routine with a variant open array parameter, specify array of const as the parameter's type. Thus

procedure DoSomething(A: array of const);

declares a procedure called DoSomething that can operate on heterogeneous arrays.

The array of const construction is equivalent to array ofTVarRec. TVarRec, declared in the System unit, represents a record with a variant part that can hold values of integer, Boolean, character, real, string, pointer, class, class reference, interface, and variant types. TVarRec's VType field indicates the type of each element in the array. Some types are passed as pointers rather than values; in particular, strings are passed as Pointer and must be typecast to string.

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.