【问题标题】:get pointer of member function delphi获取成员函数delphi的指针
【发布时间】:2012-05-05 08:29:47
【问题描述】:

在 Lazarus / delphi 中有一些技巧如何获取成员函数的指针吗? 我有这段无法编译的代码....

错误是 在德尔福:
variable required

在拉撒路:
Error: Incompatible types: got "<procedure variable type of function(Byte):LongInt of object;StdCall>" expected "Pointer"


代码:

  TClassA = class
  public
      function ImportantFunc(AParameter: byte): integer; stdcall;
  end;

  TClassB = class
  public
     ObjectA: TClassA;
     ImportantPtr: pointer;
     procedure WorkerFunc;
  end;

  function TClassA.ImportantFunc(AParameter: byte): integer; stdcall;
  begin
     // some important stuff
  end;

  procedure TClassB.WorkerFunc;
  begin
     ImportantPtr := @ObjectA.ImportantFunc; //  <-- ERROR HERE
  end;

谢谢!

【问题讨论】:

    标签: delphi function pointers lazarus


    【解决方案1】:

    成员函数不能由单个指针表示。它需要两个指针,一个用于实例,一个用于代码。但这是实现细节,您只需要使用方法类型:

    type
      TImportantFunc = function(AParameter: byte): integer of object; stdcall;
    

    然后您可以将 ImportantFunc 分配给这种类型的变量。

    由于您使用的是 stdcall,我怀疑您正试图将其用作 Windows 回调。这对于成员函数是不可能的。你需要一个全局作用域的函数,或者一个静态函数。

    【讨论】:

    • 为什么不可能?他可以将方法定义为class-method 并将TMethod.Code 指针作为回调传递吗?还是不行?
    • @David:你是对的。我想用它作为回调。但是TClassA 实际上是TCollectionItem(!)所以每个项目都必须有自己的windows回调:(因此不可能在全局范围内定义它。这很糟糕,但我不敢相信这是不可能的.
    • @teran 必须是静态的而不是类方法
    • @DavidHeffernan 是的。有趣的问题,我们几乎没有TClassA.. 的实例,对于每个我们想要传递(指向this)方法的实例作为回调。但是静态方法对于所有实例都是相同的,它不能访问self 字段等。同时我们希望这个方法使用每个单独的TClassA 实例的一些数据。可能在这种情况下,我们可以使用TRttiMethodCreateImplementation 的使用匿名函数的方法,它使用实例字段? (哦,看来我的英语不太好(:)
    • 通常回调函数包括允许将状态和/或实例信息传输到回调的参数。你的回调会这样做吗?
    【解决方案2】:
    type
      TImportantFunc = function(AParameter: byte): integer of object;stdcall;
    
      ImportantPtr: TImportantFunc;
    
    procedure TClassB.WorkerFunc;
    begin
       ImportantPtr := ObjectA.ImportantFunc; //  <-- OK HERE
    end;
    

    【讨论】:

      【解决方案3】:

      ObjectA.ImportantFunc 不是内存位置,因此地址运算符 @ 不能应用于它 - 因此编译器错误。它是 2 个指针,@TClassA.ImportantFunc(方法代码)和ObjectA(自变量)。您的问题的答案取决于您真正需要什么 - 代码指针、Self、两者都有或没有。


      如果您只需要限定函数名的范围,请使用静态类方法

      TClassA = class
      public
       class function ImportantFunc(Instance: TClassA; AParameter: byte): integer;
                                                                     stdcall; static;
      end;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-12-01
        • 2012-02-10
        • 1970-01-01
        • 2020-12-11
        • 1970-01-01
        • 1970-01-01
        • 2011-04-29
        相关资源
        最近更新 更多