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