FreePascal RTTI。有没有办法调用方法?

时间:2016-03-23 20:47:50

标签: delphi runtime rtti fpc

我试图找出是否有办法做类似于Delphi的增强型RTTI功能。

据我所知,FPC没有提供自Delphi 2010以来Delphi中出现的RTTI功能。但是我想在运行时找到一些方法来做一些技巧。

在FPC中使用typinfo单位我可以执行以下操作:

  • 获取对象发布的属性列表 - 来自getPropList单元的typinfo;
  • 获取/设置对象发布的属性的值 - 通过GetPropValue(...): Variant / SetPropValue(...Value: Variant);
  • 通过MethodAddres;
  • 发布方法

但我还没有办法做某些事情

  • 通话方法;
  • 调用构造函数,或创建对象;

更新:构造函数的问题很像方法一 - 我希望有一种方法可以传递不同的参数:

// concept of code
type

TClass = class of TObject;

TMyClass1 = class
  public
    constructor Create(Param1: Integer; Param2: string); override;
  end;

TMyClass2 = class
  public
    constructor Create(ObjectParam: Object); override;
  end;

TParams = array of Variant;

var 
Classes: array of TClass 
Instances: array of Object;
ParamArray: array of TParams;

... 

For I := 0 to Count-1 do 
begin
  LocalConstructor := @(Classes[I].Create);
  Instances[I] := CallConstructor(LocalConstructor, ParamArray[I]);
end;

所以我需要在不知道签名的情况下调用构造函数。

所以我的问题是调用Object的方法并将一些参数传递给它。它可能看起来像function CallMethod(Instance: Object; MethodName: String; Params: array of Variant): Variant;

如果我没有弄错,可以通过Delphi的2010+ RTTI来解决。但在使用增强型Delphi的RTTI之前,我想了解FPC是否可行。

换句话说,我当前的问题是将例程传递给例程。 我知道可以使用这个方案来完成:

type
  TmyProc = procedure CallMe(x: byte);
...
  var proc: TmyProc;
...
  proc := pointerToFunc^;
  proc(0);

但我需要在不知道参数的计数和类型的情况下(在编译期间)实现它。

有一些与该主题相关的链接:

Delphi: Call a function whose name is stored in a string

http://www.swissdelphicenter.ch/torry/showcode.php?id=1745

第二篇文章(http://www.swissdelphicenter.ch/torry/showcode.php?id=1745)描述了一种将参数传递给按名称从DLL导入的例程的方法。这几乎是我想要的。但我不确定这种方式是否可靠。

也许有任何图书馆,使用" old"来实现这些东西。 typinfo单元(没有RTTI单元)?

此外,我对创建某种通用事件处理程序感兴趣 - 可以分配给不同事件(具有不同参数集)的过程,例如:

procedure myEventHandler(params: array of variant);
...
Button.OnClick := myEventHandler;
Button.OnMouseMove := myEventHandler;
这可能吗?或者至少与它类似的东西?

1 个答案:

答案 0 :(得分:5)

  1. 您可以使用MethodAddress调用方法,甚至不发布方法,但是您需要确保正确的参数列表。
  2. 您可以使用元类(类引用)调用构造函数,可以在TCollection中看到它的示例:您在运行时传递集合项的类,然后可以在需要时创建它。通过使用虚拟(也可能是抽象)构造函数定义抽象类,您可以提出您希望的参数列表,例如here
  3. AFAIK无法在运行时确定参数列表,但如果您同时设计了要调用的方法和调用者本身,则有许多方法可以实现类似的行为。
  4. 例如,您传递变量打开数组(Array of const),因为它在Format()中完成,因此参数的数量及其类型可能会有所不同。但即使只有一个指针作为参数,你确定可以传递任意多个,你需要做的只是想出一些它将导致的类。