0

I have an interface (in fact multiple interfaces) which I'd like to use this way:

  • Make Units where the interfaces are declared available inside the dwscript script (if neccessary).

  • Create the objects, that implement the interfaces, in the host application written in Delphi.

  • Make those interfaces available in some way to the dwscript script.

  • And use them normally inside the script.

Is there any possibility to do so?

I tried to provide methods returning those interfaces in a class, but when I used this class over RTTI those methods where not found.

  • To my knowledge this isn't possible at the moment. Interfaces can be declared in a TdwsUnit but it isn't possible to actually implement the interfaces Delphi side. See also: [dwsUnit: function returning interface](https://bitbucket.org/egrange/dwscript/issues/6/dwsunit-function-returning-interface) – SpeedFreak Sep 13 '15 at 09:27
  • 1
    Actually _it is_ possible. Just not the way one would expect. Give me a sec to type in an answer... – SpeedFreak Sep 13 '15 at 11:29

1 Answers1

1

As I stated above it isn't immediately possible to declare an interface and implement it Delphi side with a TdwsUnit. It is however possible to achieve what you're after in other ways.

I'm assuming that you have declared both your interface and your class in a TdwsUnit. Let's call them IMyInterface and TMyClass.

type
  IMyInterface = interface
    procedure SetValue(const Value: string);
    function GetValue: string;
    property Value: string read GetValue write SetValue;
    procedure DoSomething;
  end;

type
  TMyClass = class(TObject)
  protected
    procedure SetValue(const Value: string);
    function GetValue: string;
  public
    property Value: string read GetValue write SetValue;
    procedure DoSomething;
  end;

Solution 1 - Alter the class declaration at run time

Create an event handler for the TdwsUnit.OnAfterInitUnitTable event and add the interface to the class declaration:

procedure TDataModuleMyStuff.dwsUnitMyStuffAfterInitUnitTable(Sender: TObject);
var
  ClassSymbol: TClassSymbol;
  InterfaceSymbol: TInterfaceSymbol;
  MissingMethod: TMethodSymbol;
begin
  // Add IMyInterface to TMyClass
  ClassSymbol := (dwsUnitProgress.Table.FindTypeLocal('TMyClass') as TClassSymbol);
  InterfaceSymbol := (dwsUnitProgress.Table.FindTypeLocal('IMyInterface') as TInterfaceSymbol);
  ClassSymbol.AddInterface(InterfaceSymbol, cvProtected, MissingMethod);
end;

Now you can access an instance of the class though an interface in your script:

var MyStuff: IMyInterface;
MyStuff := TMyObject.Create;
MyStuff.DoSomething;

Solution 2 - Use duck typing

Since DWScript supports duck typing you don't actually need to declare that your class implements an interface. Instead you just state what interface you need and let the compiler figure out if the object can satisfy that need:

var MyStuff: IMyInterface;
MyStuff := TMyObject.Create as IMyInterface;
MyStuff.DoSomething;
SpeedFreak
  • 876
  • 6
  • 16
  • Thank you. It works, but I find it rather complicated. At the moment we are having a look at alternatives, paxCompiler for example. It supports interfaces directly and supports mobile platforms. – Sebastian Jänicke Oct 03 '15 at 15:26