2012-07-12 10 views
7

델파이 부분 :인터페이스 객체를 파스칼 스크립트 함수 호출에 전달하는 방법은 무엇입니까?

나는 이벤트와 클래스를 가지고 그 사건에서 나는 그것에 인터페이스 객체를 전달하는 프로 시저를 호출 할 필요가있다. 그것은 델파이에서 잘 작동하지만 파스칼 스크립트에서 선언하는 데 문제가 있습니다. 배경으로

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

파스칼 스크립트 편집 부분 :

내 목표는 파스칼 스크립트에서 이벤트를 사용할 수있는 클래스를 갖게하고 그 인터페이스 된 객체를 위에서와 같은 프로 시저로 전달해야하기 때문에 처음으로 컴파일 시간을 선언하려고 시도했습니다. (하지만 저는 아닙니다. 심지어는) 그렇게 할 수있는 올바른 방법이 있는지 있다면 :

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

파스칼 스크립트 실행 부분 : 나는 확실히 잃었어요

런타임 부분입니다. 나는 호출 스택에서 인터페이스 객체를 얻는 방법을 알아 내 RenderObject 절차에 전달할 수 없습니다

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; 

그리고 질문은 :

는 사람이 어떻게 저를 제안 할 수 올바르게이 경우에 대한 컴파일 및 런타임 부분을 정의하거나 어떻게 든 인터페이스 객체를 전달하면서 수정합니까?

P. 그 Inno-Setup 태그에 대해 미안하지만 어쩌면 누군가 에서 InnoSetup을 사용자 정의하려고 시도했습니다.

고맙습니다.

답변

1

내가 묻는 바를 이해하면 인터페이스를 매개 변수로 메소드에 전달하려고합니다. 불행히도 정확한 대답은 없지만 PascalScript의 전역 변수에 인터페이스를 할당하는 방법을 알고 있습니다. 다음은 Castalia에서 수행하는 작업입니다.

PSScript OnCompile 이벤트에서 PS.Comp.AddInterface를 사용하여 인터페이스를 추가 한 다음 필요한 각 메서드를 추가합니다. 그런 다음 인터페이스 유형의 변수를 추가하십시오.OnExectute 이벤트, 인스턴스에 이전에 만든 변수를 결합,

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'); 

다음 :

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

그 일을하는 데, 스크립트는 인터페이스 개체에 액세스 할 수 있습니다 그것은 예를 들어, 다음과 같습니다 변수를 통해이 인스턴스에서 스크립트는 Clipboard.GetText에 대한 호출을 포함 할 수 있으며 예상대로 작동합니다.

이는 테스트를 거쳐 작동합니다.

이제 TPSScript.ExecuteFunction을 사용하여 위에 나온 PIFVariant를 전달하여 원하는 것에 더 가까이 접근 할 수 있다고 생각합니다. 그러나 그것은 내가 테스트 해본 것이 아닙니다.

행운을 빈다.

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
  • 그런 x.GetProc 방법을 사용하여 프로 시저 번호를 얻으
  • 다음
  • 이 TPSVariantClass var에 만들기 클래스 인스턴스를 할당 TPSList 형의 인수 목록을 (생성하는 그 데이터 필드에) 전달해야
  • 또한 VI.FType 필드에 x.FindType2 (btClass)을 할당 (이 작동하는 이유를 전혀 생각)
  • 가 TPSList 목록에 TPSVariantClass 변수에 대한 포인터를 추가이 없습니다
  • .......... 프로 시저를 호출합니다. x.RunProc (argList, proc); 여기서 proc는 이전에 얻은 프로 시저의 수입니다.

이것은 클래스에서 작동하지만 인터페이스에서 크게 다르지 않아야합니다. TPSVariantClass 대신 인수 변수에 TPSVariantInterface 유형을 사용하십시오. 그 외 모든 것은 같음이어야합니다.

아마도 도움이되기를 바랍니다.