2012-04-17 13 views
7

Escribí un script para las aplicaciones y mi objetivo es posibilitar la publicación de cualquier tipo de delphi en el script. Yo uso rtti para automatizar esta tarea. Para cualquier tipo de instancia como clases, uso el siguiente código para buscar y llamar a un método desde el script.Delphi - Método de grabación de invocación por nombre

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; 

Pero con un récord este código no funciona, porque el tipo TRttiMethod no ofrece un método Invoke() para los tipos de registro. Puedo acceder a las informaciones del método mediante Info.GetMethod ('AMethod') desde el tipo de registro.
Por ejemplo, tengo un disco como este:

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

Así que ¿alguien sabe una manera de invocar un método de un registro si tengo methodname o methodaddress?

+0

¿Acaba de reinventar [DWScript] (http://code.google.com/p/dwscript/)? –

+0

Gracias por la pista, pero sé DWScript. Mi lenguaje está destinado a ser una interfaz de script para un programa delphi donde construcciones como AObject.AFunction.AObject.DoSomething son posibles. – DragonFlyOfGold

+2

Pensé que DWScript podría hacer todo eso, pero quizás estoy equivocado –

Respuesta

12

Después de explorar los enlaces en la documentación delphi publicada en los comentarios anteriores, eché un vistazo más de cerca al tipo delphi TRttiRecordMethod en System.Rtti. Proporciona el método DispatchInvoke() y este método espera un puntero. Así siguiente código funciona:

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; 

Si desea llamar a un método estático o el operador sobrecargado el código no funciona. Delphi internamente siempre agrega el puntero a lista de parámetros, pero esto provocará unvio de acceso. Entonces use este código:

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

¡Gracias, esto realmente me ayudó en mi búsqueda de una forma de llamar dinámicamente a un servicio web SOAP! – dahook

Cuestiones relacionadas