2012-07-12 19 views
7

デルファイ一部:インタフェースされたオブジェクトをPascal Script関数呼び出しに渡すには?

私は、イベントを持つクラスを持っているし、そのイベントから、私はそれにインタフェースオブジェクトを渡す手順を呼び出す必要があります。 Delphiでは正常に動作しますが、Pascal Scriptで宣言する際に問題があります。バックグラウンドに

は - IGPGraphicsインタフェースは Delphi GDI+ libraryの一部であり、方法はなく、このように定義されています

type 
    IGdiplusBase = interface 
    ['{24A5D3F5-4A9B-42A2-9F60-20825E2740F5}'] 
    IGPGraphics = interface(IGdiPlusBase) 
    ['{57F85BA4-CB01-4466-8441-948D03588F54}'] 

次は私がパスカルスクリプトで何をする必要があるかだけの簡素化デルファイの擬似コードです:

type 
    TRenderEvent = procedure(Sender: TObject; const GPGraphics: IGPGraphics) of object; 
    TRenderClass = class(TGraphicControl) 
    private 
    FOnRender: TRenderEvent; 
    public 
    property OnRender: TRenderEvent read FOnRender write FOnRender; 
    end; 

// when the TRenderClass object instance fires its OnRender event I want to call 
// the RenderObject procedure passing the IGPGraphics interfaced object to it; I 
// hope I'm doing it right, I'm just a newbie to this stuff - but it works so far 
// in Delphi (since I didn't get it to work in Pascal Script) 

procedure TForm1.RenderClass1Render(Sender: TObject; const GPGraphics: IGPGraphics); 
begin 
    RenderObject(GPGraphics, 10, 10); 
end; 

// what I need in Pascal Script is between these two lines; just pass the interface 
// object from the event fired by component to the procedure called from inside it 

procedure RenderObject(const GPGraphics: IGPGraphics; X, Y); 
begin 
    // and here to work with the interfaced object somehow 
end; 

パスカルスクリプトのコンパイルの一部:

私の目的は、イベントを持つクラスをPascal Scriptで利用できるようにすることであり、上記のように、そのインタフェースされたオブジェクトをそのプロシージャに渡す必要があるため、最初にコンパイル時に宣言しようとしました(しかし、でもそれはそうする正しい方法の場合)を確認してください。

// the interface 
PS.AddInterface(Cl.FindInterface('IUnknown'), StringToGuid('{57F85BA4-CB01-4466-8441-948D03588F54}'), 'IGPGraphics'); 
// the type for the event 
PS.AddTypeS('TRenderEvent', 'procedure(Sender: TObject; const GPGraphics: IGPGraphics)'); 
// and the class with the event itself 
with PS.AddClassN(PS.FindClass('TGraphicControl'), 'TRenderClass') do 
begin 
    RegisterProperty('OnRender', 'TRenderEvent', iptrw); 
end; 

パスカルスクリプトランタイム一部:

私は間違いなく、迷ってしまいましたランタイム部分です。

function RenderClassProc(Caller: TPSExec; Proc: TPSExternalProcRec; Global, 
    Stack: TPSStack): Boolean; 
var 
    PStart: Cardinal; 
begin 
    PStart := Stack.Count-1; 
    Result := True; 
    if Proc.Name = 'RENDEROBJECT' then 
    begin 
    // how do I get the interfaced object from Stack (or whatever else) and pass 
    // it to the RenderObject proc here ? I can't find anything related about it 
    // except functions that has no parameter index 
    RenderObject(Stack.Get ?, Stack.GetInt(PStart-2), Stack.GetInt(PStart-3)); 
    end; 
end; 

をし、問題がある:私は、コールスタックからのインターフェースオブジェクトを取得し、私のRenderObject手順にそれを渡す方法を見つけ出すことはできません

誰がどのように私を提案することができますこのケースのコンパイルと実行時の部分を正しく定義するか、どういうわけか、インタフェースされたオブジェクトを渡して修正しますか?

P.S.そのInno-Setupタグは残念ですが、たぶん誰か InnoSetupをこのようにカスタマイズしようとしました。

ありがとうございます!

答えて

1

あなたが求めていることを理解している場合は、メソッドのパラメータとしてインターフェイスを渡す必要があります。残念ながら、私はそれに正確な答えはありませんが、私はPascalScriptのグローバル変数にインターフェイスを割り当てる方法を知っています。

PSScript OnCompileイベントで、PS.Comp.AddInterfaceでインターフェイスを追加し、必要なメソッドをそれぞれ追加します。その後、インタフェースタイプの変数を追加します。これは、例えば、次のようになります。

with PS.Comp.AddInterface(ARunner.Comp.FindInterface('IUnknown'), 
    StringToGUID('{0346F7DF-CA7B-4B15-AEC9-2BDD680EE7AD}'), 
    'ICastaliaMacroClipboardAccess') do 
begin 
    RegisterMethod('function GetText: string', cdRegister); 
    RegisterMethod('procedure SetText(AText: string)', cdRegister); 
end; 
PS.AddRegisteredVariable('Clipboard', 'ICastaliaMacroClipboardAccess'); 

その後、OnExectuteイベントで、インスタンスに以前に作成した変数をバインド:

P := PS.GetVariable('Clipboard'); //P is type PIFVariant 
SetVariantToInterface(P, Implementing object as ICastaliaMacroClipboardAccess);  

スクリプトはインターフェース化オブジェクトへのアクセス権を持っている、ことを行ってましたこの例では、スクリプトにはClipboard.GetTextの呼び出しが含まれていて、期待通りに機能します。

これはテスト済みであり、動作します。

ここでは、あなたが望むものに近づくために、上記のPIFVariantを渡してTPSScript.ExecuteFunctionを使用できると推測します。それは私がテストしたものではありません。

幸運を祈る!

1

信じがたいですが、私はこれは何をすべきか、基本的にはそれを

procedure TApp.CallProcedureWithClassArg(x: TPSExec); 
var 
    o: TSampleObject; 
    argumentList: TPSList; 
    arg1: TPSVariantClass; 
    proc: Integer; 
begin 
    o := TSampleObject.Create; 
    o.X := 1; // do something with the object maybe 
    proc := x.GetProc('TakeThis'); 
    argumentList := TPSList.Create; 
    arg1.VI.FType := x.FindType2(btClass); 
    arg1.Data := o; 
    argumentList.Add(@arg1); 
    x.RunProc(argumentList, proc); 
    argumentList.Free; 
end; 

を行う方法を発見しました。

  • ユーザーごTPSExecインスタンス、のはx.GetProc方法
  • を使用してプロシージャ番号を取得後、X
  • を言わせて、あなたのクラスのインスタンスを割り当て、TPSVariantClassのVARを作成TPSListタイプ
  • の引数リストを作成します(これは)は、そのデータフィールドに
  • もx.FindType2(btClass)をそのVI.FTypeフィールドに割り当てます(これがなぜ機能するのか全く分かりません)
  • TPSVariantClass変数へのポインタをTPSListリストに追加します
  • ..........プロシージャx.RunProc(argList、proc)を呼び出します。ここでprocは以前に取得したプロシージャの番号です

これはクラスでは機能しますが、インタフェースであまり違いはありません.TPSVariantClassの代わりにTPSVariantInterface型を引数として使用してください。他のすべてはと同じである必要があります。

私はこれが多分誰かを助けることを望みます。

関連する問題