【问题标题】:FreePascal RTTI. Is there a way to invoke method?FreePascal RTTI。有没有办法调用方法?
【发布时间】:2016-03-23 20:47:49
【问题描述】:

我正在尝试找出是否有类似于 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;

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

所以我的问题是调用一个对象的方法并传递一些参数给它。它可能看起来像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 导入的例程的方法。我想这几乎是我需要的。但我不确定这种方式是否可靠。

也许有任何库,它使用“旧” typinfo 单元(没有 RTTI 单元)来实现这些东西?

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

procedure myEventHandler(params: array of variant);
...
Button.OnClick := myEventHandler;
Button.OnMouseMove := myEventHandler;

这可能吗?或者至少是类似的东西?

【问题讨论】:

    标签: delphi runtime rtti fpc


    【解决方案1】:
    1. 您可以使用MethodAddress 调用方法,甚至是未发布的方法,但您可以确保参数列表正确无误。
    2. 您可以使用元类(类引用)调用构造函数,其示例可以在 TCollection 中看到:您在运行时传递集合项的类,然后可以在需要时创建它。通过用虚拟(也可能是抽象的)构造函数定义抽象类,你可以想出你想要的参数列表,例如here
    3. AFAIK 无法在运行时确定参数列表,但如果您同时设计要调用的方法和调用者本身,则可以通过多种方式实现类似的行为。

    例如,您传递变体开放数组 (Array of const),就像在 Format() 中所做的那样,因此参数的数量及其类型可能会有所不同。但是即使只有一个指针作为参数,你也可以传递任意数量的参数,你需要做的就是想出一些它会引导的类。

    【讨论】:

      猜你喜欢
      • 2010-12-24
      • 1970-01-01
      • 2013-09-20
      • 2011-05-20
      • 2020-10-23
      • 2022-11-18
      • 2013-04-01
      • 2019-06-30
      • 1970-01-01
      相关资源
      最近更新 更多