2014-12-16 8 views
7

Dato un riferimento IScriptObj, come si arriva a uno IInfo o TProgramInfo corrispondente?DWScript: passaggio da IScriptObj a IInfo o TProgramInfo


Ho un oggetto di script che include un oggetto Delphi.

Per gestire la durata dell'oggetto di script, l'oggetto Delphi memorizza un riferimento all'oggetto di script. L'oggetto Script è dichiarato con un componente TdwsUnit. E 'abbastanza standard e più o meno così:

Delphi

type 
    TDelphiObject = class 
    private 
    FScriptObject: IScriptObj; 
    public 
    procedure DoSomething; 
    property ScriptObject: IScriptObj read FScriptObject write FScriptObject; 
    end; 

Script

type 
    TScriptObject = class 
    protected 
    procedure DoSomething; virtual; 
    public 
    constructor Create; 
    end; 

l'istanza dell'oggetto Delphi e la configurazione dei collegamenti Delphi/script accade nel Implementazione di Delphi del costruttore di oggetti script. Anche abbastanza standard:

Delphi

// Implements TScriptObject.Create 
procedure TMyForm.dwsUnitClassesTScriptObjectConstructorsCreateEval(Info: TProgramInfo; var ExtObject: TObject); 
var 
    DelphiObject: TDelphiObject; 
    DelphiObjectInfo: IInfo; 
begin 
    // Create the Delphi-side object 
    DelphiObject := TDelphiObject.Create; 

    // Get the script object "self" value 
    DelphiObjectInfo := Info.Vars['self']; 

    // Store the ScriptObject reference 
    DelphiObject.ScriptObject := DelphiObjectInfo.ScriptObj; 

    // Return the instance reference to the script 
    ExtObject := DelphiObject; 
end; 

Idealmente avrei risparmiato il riferimento IInfo piuttosto che il IScriptObj dal IInfo fa tutto quello che ho bisogno in seguito, ma per esperienza sembra l'oggetto IInfo è valida solo per la durata della chiamata al metodo.

In ogni caso, il problema si verifica in seguito quando TDelphiObject.DoSomething viene richiamato sul lato Delphi. TDelphiObject.DoSomething è destinato a richiamare il metodo virtuale corrispondente sull'oggetto script:

Delphi

procedure TDelphiObject.DoSomething; 
var 
    Info: IInfo; 
    DoSomethingInfo: IInfo; 
begin 
    // I have a IScriptObj but I need a IInfo... 
    Info := { what happens here? }; 

    // Call the virtual DoSomething method 
    DoSomethingInfo := Info.Method['DoSomething']; 
    DoSomethingInfo.Call([]); 
end; 

Ho provato molte tecniche diverse per ottenere una utilizzabile IInfo o TProgramInfo dallo stored IScriptObj ma ogni cosa ha fallito. Allora, qual è il modo corretto di farlo?

+0

Non ho molto expirience con DWScript ma sei sicuro di aver chiamato il tuo metodo di script nel modo giusto? Basata su un rapido sguardo su DWS Wiki (http://code.google.com/p/dwscript/wiki/FirstSteps#Functions), la chiamata corretta sarebbe "Info.Method ['DoSomething']. Call ([]); " – SilverWarior

+0

Le due espressioni sono equivalenti; La proprietà 'Method []' restituisce un riferimento all'interfaccia 'IInfo'. – SpeedFreak

+0

Puoi mostrare la dichiarazione di TProgramInfo? –

risposta

1

Il problema si è verificato supponendo di aver bisogno di un'interfaccia IInfo per incapsulare l'istanza dell'oggetto ma apparentemente DWScript non funziona in questo modo. Quello di cui ho bisogno è di creare un riferimento/puntatore temporaneo all'istanza e quindi creare uno IInfo su quello.

Ecco come ciò che si fa:

procedure TDelphiObject.DoSomething; 
var 
    ProgramExecution: TdwsProgramExecution; 
    ProgramInfo: TProgramInfo; 
    Data: TData; 
    DataContext: IDataContext; 
    Info: IInfo; 
    DoSomethingInfo: IInfo; 
begin 
    (* 
    ** Create an IInfo that lets me access the object represented by the IScriptObj pointer. 
    *) 

    // FProgramExecution is the IdwsProgramExecution reference that is returned by 
    // TdwsMainProgram.CreateNewExecution and BeginNewExecution. I have stored this 
    // elsewhere. 
    ProgramExecution := TdwsProgramExecution(FProgramExecution); 
    ProgramInfo := ProgramExecution.AcquireProgramInfo(nil); 
    try 
    // Create a temporary reference object 
    SetLength(Data, 1); 
    Data[0] := FScriptObject; 
    ProgramInfo.Execution.DataContext_Create(Data, 0, DataContext); 
    // Wrap the reference 
    Info := TInfoClassObj.Create(ProgramInfo, FScriptObject.ClassSym, DataContext); 


    // Call the virtual DoSomething method 
    DoSomethingInfo := Info.Method['DoSomething']; 
    DoSomethingInfo.Call([]); 

    finally 
    ProgramExecution.ReleaseProgramInfo(ProgramInfo); 
    end; 
end; 

Quello che fa è l'oggetto di abilitazione orientato chiamata spalle da Delphi per lo script. Senza questo è possibile chiamare funzioni di script globali solo da Delphi.

FWIW, le seguenti due righe di cui sopra:

ProgramInfo.Execution.DataContext_Create(Data, 0, DataContext); 
Info := TInfoClassObj.Create(ProgramInfo, FScriptObject.ClassSym, DataContext); 

può essere sostituito con una chiamata a CreateInfoOnSymbol (dichiarata in dwsInfo):

CreateInfoOnSymbol(Info, ProgramInfo, FScriptObject.ClassSym, Data, 0);