DWScript: Property getter/setter for object

83 Views Asked by At

The tdwsUnit declares a property of type TObject, as well as a getter and a setter. An instantiated object shall be stored in an "object store" on the Delphi side. The goal is to transport the object from script A to script B, where script A, when run, creates and stores the object on the Delphi side and script B, when run (same Delphi process) shall read the object from the Delphi side and use it.

Var ObjectStore : TObject;

procedure TDWSLibTools.TApp_GetObject(Info: TProgramInfo; ExtObject: TObject);
begin
 // How to return object in ObjectStore?
 <ResultOfThisGetter> := ObjectStore;
end;

procedure TDWSLibTools.TApp_SetObject(Info: TProgramInfo; ExtObject: TObject);
begin
 // How to access the object in parameter named "Value"?
 ObjectStore := Info.Vars['Value'].Get?????
end;

And: Even when done correctly, will the object "survive" between the script runs?

1

There are 1 best solutions below

4
AndersMelander On

You can expose any Delphi object instance to any script, so there shouldn't be a problem with creating a Delphi object in one script and accessing that object from another script.

It sounds like your object is initially being created from the script. I'm assuming that this object is declared on the Delphi side and the class type then exposed to the script somehow - e.g. via a TdwsUnit component.

For example on the Delphi side you have a TDelphiClass declared and you have a corresponding script class called TScriptClass. I'm further assuming that you have declared a TApp script class (e.g. in a TdwsUnit) with an Object property so the script side API looks something like this:

type
  TApp = class
  protected
    function GetObject: TScriptClass;
    procedure SetObject(Value: TScriptClass);
  public
    property Object: TScriptClass read GetObject write SetObject;
  end;

Now, as far as I can tell you are just asking how to implement the GetObject and SetObject TdwsUnit event handlers on the Delphi side. In the following example I assume that your ObjectStore variable if of the type TDelphiClass (to make it more obvious where I reference it):

var
  ObjectStore: TDelphiClass;


// TScriptClass.Create
procedure TDataModuleScript.dwsUnitStuffClassesTScriptClassConstructorsCreateEval(
  Info: TProgramInfo; var ExtObject: TObject);
begin
  if (ExtObject = nil) then
    ExtObject := TDelphiClass.Create;
end;

// TApp.GetObject: TScriptObject
procedure TDataModuleScript.dwsUnitStuffClassesTAppMethodsGetObjectEval(
  Info: TProgramInfo; ExtObject: TObject);
var
  ClassSym: TClassSymbol;
  ScriptObj: IScriptObj;
begin
  // Get the script side class type
  ClassSym := TClassSymbol(Info.FindSymbolInUnits('TScriptClass'));

  if (ClassSym <> nil) then
  begin
    // We're not using the TApp Delphi side object here, but if 
    // there is one then ExtObject would point to it.

    // Create a script side object to represent the Delphi side object
    ScriptObj := TScriptObjInstance.Create(ClassSym, Info.Execution);

    // Store a reference to the Delphi side object inside the 
    // script side object
    ScriptObj.ExternalObject := ObjectStore;

    // Return the script side object
    Info.ResultAsVariant := ScriptObj;
  end;
end;

// TApp.SetObject(Value: TScriptObject)
procedure TDataModuleScript.dwsUnitStuffClassesTAppMethodsSetObjectEval(
  Info: TProgramInfo; ExtObject: TObject);
var
  ParamInfo: IInfo;
  ExtObj: TDelphiClass;
begin
  // Get the parameter value
  ParamInfo := Info.Vars['Value'];
  if (ParamInfo.ValueIsEmpty) then
    // parameter is nil
    ExtObj := nil 
  else
    // Parameter is object.
    // Get the Delphi side reference and case to correct 
    // type (with type check)
    ExtObj := ParamInfo.ExternalObject as TDelphiClass;

  // Stash the reference to the Delphi side object
  ObjectStore := TDelphiClass(ExtObj);
end;