给定IScriptObj引用,如何获得相应的IInfo或TProgramInfo
我有一个脚本对象包装了一个Delphi对象。
为了管理脚本对象的生存期,Delphi对象存储对脚本对象的引用。脚本对象是用TdwsUnit组件声明的。这是相当标准的,而且是这样的:
Delphi
type
TDelphiObject = class
private
FScriptObject: IScriptObj;
public
procedure DoSomething;
property ScriptObject: IScriptObj read FScriptObject write FScriptObject;
end;脚本
type
TScriptObject = class
protected
procedure DoSomething; virtual;
public
constructor Create;
end;Delphi对象的实例化和Delphi/script链接的设置发生在script对象构造函数的Delphi实现中。同样非常标准的:
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;理想情况下,我应该保存IInfo引用,而不是IScriptObj,因为IInfo完成了以后所需的一切,但是从经验来看,IInfo对象只在方法调用的持续时间内有效。
无论如何,当在Delphi端调用TDelphiObject.DoSomething时,这个问题会在稍后发生。TDelphiObject.DoSomething用于调用脚本对象上相应的虚拟方法:
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;为了从存储的IInfo或TProgramInfo中获得可用的IScriptObj,我尝试了许多不同的技术,但是每件事都失败了。那么,正确的做法是什么呢?
发布于 2014-12-21 18:37:50
问题是,我假设我需要一个IInfo接口来封装对象实例,但显然DWScript不是这样工作的。我需要的是创建一个对实例的临时引用/指针,然后在上面创建一个IInfo。
这是如何做到的:
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;这样做是启用从Delphi到脚本的面向对象的回调。没有这一点,就只能从Delphi调用全局脚本函数。
FWIW,上述两行:
ProgramInfo.Execution.DataContext_Create(Data, 0, DataContext);
Info := TInfoClassObj.Create(ProgramInfo, FScriptObject.ClassSym, DataContext);可以用对CreateInfoOnSymbol的调用(在dwsInfo中声明)代替:
CreateInfoOnSymbol(Info, ProgramInfo, FScriptObject.ClassSym, Data, 0);https://stackoverflow.com/questions/27507501
复制相似问题