2012-04-17 2 views
7

내 응용 프로그램에 대한 scriptlanguage를 작성했습니다. 목표는이 스크립트에서 delphi의 모든 유형을 게시 할 수 있도록하는 것입니다. 나는이 작업을 자동화하기 위해 rtti를 사용한다. 클래스와 같은 인스턴스 유형의 경우 스크립트에서 메소드를 찾아 호출하기 위해 다음 코드를 사용합니다. TRttiMethod 유형이 레코드 유형에 대한 호출() 메소드를 제공하지 않기 때문에 Delphi - 이름 당 레코드 메서드 호출

var Info : TRttiType; 
    Meth : TRttiMethod; 
    Param : TArray<TValue>; 
    Result : TValue; 
    AnyClass : TClass; 
begin 
    ... 
    Info := RttiContext.GetType(AnyClass); 
    Meth := Info.GetMethod('AMethod'); 
    Setlength(Param, 1); 
    Param[0] := TValue.From<Integer>(11); 
    Result := Meth.Invoke(ClassInstance, Param); 
    ... 
end; 

하지만이 코드가 작동하지 않는 레코드

. 레코드 유형에서 Info.GetMethod ('AMethod')에 의해 메소드 정보에 액세스 할 수 있습니다.

TRecordType = record 
    Field1, Field2 : single; 
    procedure Calc(Value : integer); 
end; 

그래서 사람이 알고 있지 내가 methodName로 또는 methodaddress이있는 경우 기록에서 메소드를 호출 할 수있는 방법 : 예를 들어
내가 이런 기록을 가지고?

+0

[DWScript] (http://code.google.com/p/dwscript/)을 새로 작성 했습니까? –

+0

힌트를 보내 주셔서 감사합니다. 그러나 저는 DWScript를 알고 있습니다. 내 언어는 AObject.AFunction.AObject.DoSomething과 같은 구조가 가능한 델파이 프로그램에 대한 스크립트 가능한 인터페이스로 사용됩니다. – DragonFlyOfGold

+2

DWScript로 모든 작업을 수행 할 수 있다고 생각했지만 아마도 틀렸어 –

답변

12

위의 주석에 게시 된 델파이 문서의 링크를 살펴본 후 System.Rtti의 델파이 형식 TRttiRecordMethod를 자세히 살펴 보았습니다. DispatchInvoke() 메서드를 제공하며이 메서드는 포인터를 필요로합니다. 그래서 다음 코드는 작동 :

TRecordType = record 
    Field1, Field2 : single; 
    procedure Calc(Value : integer);  
end; 


    Meth : TRttiMethod; 
    Para : TRttiParameter; 
    Param : TArray<TValue>; 
    ARec : TRecordType; 
begin 
    Info := RttiContext.GetType(TypeInfo(TRecordType)); 
    Meth := Info.GetMethod('Calc'); 
    Setlength(Param, 1); 
    Param[0] := TValue.From<Integer>(12); 
    Meth.Invoke(TValue.From<Pointer>(@ARec), Param); 
end; 

정적 방법 또는 코드가 작동하지 않는 오버로드 된 연산자를 호출합니다. 델파이는 내부적으로 항상 parameterlist에 자체 포인터를 추가하지만, 이는 액세스 위반의 원인이됩니다. 따라서이 코드를 대신 사용하십시오.

Meth : TRttiMethod; 
    Para : TRttiParameter; 
    Param : TArray<TValue>; 
    ARec : TRecordType; 
begin 
    Info := RttiContext.GetType(TypeInfo(TRecordType)); 
    Meth := Info.GetMethod('&op_Addition'); 
    ... 
    Meth.Invoke(TValue.From<Pointer>(@ARec), Param); 
    Result := System.Rtti.Invoke(Meth.CodeAddress, Param, Meth.CallingConvention, Meth.ReturnType.Handle, Meth.IsStatic); 
end;  
+0

감사합니다. 이것은 SOAP 웹 서비스를 동적으로 호출하는 방법을 찾는 데 정말로 도움이되었습니다! – dahook