方法指针的 RTTI 信息

2023-12-11

是否可以获取有关某个设备的 RTTI 信息TMethod?

我可以通过以下方式获取实例

Instance := TObject(Method.Data);

这样我就可以获得实例的RTTI类型,但是如何才能获得正确的TRttiMethod?我想检查使用方法指针传入的方法的属性。


这种方法在理论上是有效的,而且在实践中也有一个很好的改变,但有一些事情可能会阻止你掌握TRttiMethod.

  • The TMethod记录说Data: Pointer, not TObject。这意味着可能存在除TObject as the Data!这是一个严重的问题,因为如果Data is not TObject,然后尝试从中提取 RTTI 将导致运行时错误。
  • 并非所有方法都有 RTTI。默认情况下,私有区域中的方法没有 RTTI,可以使用{$RTTI}也停止为公共或已发布成员生成 RTTI。

对于我们在 Delphi 中的通常类型的事件实现来说,这两个问题不会成为问题(双击对象检查器中的事件名称并填写代码),但话又说回来,我不认为你是谈论“vanila”实现。没有多少人会用属性来装饰默认的事件处理程序!

演示上述所有内容的代码:

program Project15;

{$APPTYPE CONSOLE}

uses
  SysUtils, RTTI;

type
  // Closure/Event type
  TEventType = procedure of object;

  // An object that has a method compatible with the declaration above
  TImplementation = class
  private
    procedure PrivateImplementation;
  public
    procedure HasRtti;

    procedure GetPrivateImpEvent(out Ev:TEventType);
  end;

  TRecord = record
    procedure RecordProc;
  end;

  // an object that has a compatible method but provides no RTTI
  {$RTTI EXPLICIT METHODS([])}
  TNoRttiImplementation = class
  public
    procedure NoRttiAvailable;
  end;

procedure TImplementation.GetPrivateImpEvent(out Ev:TEventType);
begin
  Ev := PrivateImplementation;
end;

procedure TImplementation.HasRtti;
begin
  WriteLn('HasRtti');
end;

procedure TNoRttiImplementation.NoRttiAvailable;
begin
  WriteLn('No RTTI Available');
end;

procedure TRecord.RecordProc;
begin
  WriteLn('This is written from TRecord.RecordProc');
end;

procedure TImplementation.PrivateImplementation;
begin
  WriteLn('PrivateImplementation');
end;

procedure TotalyFakeImplementation(Instance:Pointer);
begin
  WriteLn('Totaly fake implementation, TMethod.Data is nil');
end;

procedure SomethingAboutMethod(X: TEventType);
var Ctx: TRttiContext;
    Typ: TRttiType;
    Method: TRttiMethod;
    Found: Boolean;
begin
  WriteLn('Invoke the method to prove it works:');
  X;
  // Try extract information about the event
  Ctx := TRttiContext.Create;
  try
    Typ := Ctx.GetType(TObject(TMethod(X).Data).ClassType);
    Found := False;
    for Method in Typ.GetMethods do
      if Method.CodeAddress = TMethod(X).Code then
      begin
        // Got the Method!
        WriteLn('Found method: ' + Typ.Name + '.' + Method.Name);
        Found := True;
      end;
    if not Found then
      WriteLn('Method not found.');
  finally Ctx.Free;
  end;
end;

var Ev: TEventType;
    R: TRecord;

begin
  try
    try
      WriteLn('First test, using a method that has RTTI available:');
      SomethingAboutMethod(TImplementation.Create.HasRtti);
      WriteLn;

      WriteLn('Second test, using a method that has NO rtti available:');
      SomethingAboutMethod(TNoRttiImplementation.Create.NoRttiAvailable);
      WriteLn;

      WriteLn('Third test, private method, default settings:');
      TImplementation.Create.GetPrivateImpEvent(Ev);
      SomethingAboutMethod(Ev);
      WriteLn;

      WriteLn('Assign event handler using handler from a record');
      try
        SomethingAboutMethod(R.RecordProc);
      except on E:Exception do WriteLn(E.Message);
      end;
      WriteLn;

      WriteLn('Assign event handler using static procedure');
      try
        TMethod(Ev).Data := nil;
        TMethod(Ev).Code := @TotalyFakeImplementation;
        SomethingAboutMethod(Ev);
      except on E:Exception do WriteLn(E.Message);
      end;
      WriteLn;

    except
      on E: Exception do Writeln(E.ClassName, ': ', E.Message);
    end;
  finally ReadLn;
  end;
end.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

方法指针的 RTTI 信息 的相关文章

  • 将字符串作为 PChar 从 CSharp 传递到 Delphi DLL

    我正在尝试将字符串从 C 传递到 Delphi 构建的 DLL Delphi DLL 需要 PChar 这是Delphi导出 procedure DLL Message Location PChar AIntValue integer st
  • 德尔福和Doxygen

    我想使用 doxygen pas2dox 记录我的源代码 当我设置好所有内容 包括过滤器和提取选项 提取所有内容 时 doxygen 运行良好 但生成的文档仅包含源文件作为链接 并且没有提取类型 方法 过滤后的源看起来不错 有任何提示如何定
  • VirtualStringTree 正确/推荐使用

    我已经使用 virtualstringtree 一段时间了 我将它用于两个不同的用途 第一个是用于选择 显示数据的普通树 第二个是作为网格来显示 SQL 语句的输出 我加载到树中的所有数据都来自数据库 对于树示例 我有一个 ParentId
  • 如何将IDL导入到Delphi中?

    我如何导入接口定义语言 idl 文件存入Delphi 将类型和接口转换为 pascal 文件 我试过了 File Open 它只显示 idl 文本文件的文本 Project 添加到项目 它只是 就像 添加了一个 idl文本文件到项目 成分
  • 如何检查文件是否有备用数据流?

    Delphi 有没有办法检查文件是否有任何备用数据流 看一下 Win32 APIFindFirstStreamW https msdn microsoft com en us library windows desktop aa364424
  • 从不同的形式调用过程

    我正在使用 Lazarus 我有一个名为TForm1单元名称为 Unit 1 在这里我有一个名为mergeDATfile a shortint 这会产生一些东西 顺便说一句 我必须创建另一个名为TForm2里面有按钮 Button1 当它被
  • 如何使用 IdTCPClient 等待来自服务器的字符串?

    我的 IdTelnet indy 10 1 有问题 我无法以 Unicode 模式从服务器读取数据 现在我想用 IdTCPClient 编写 telnet 终端 服务器有时发送一行 有时发送越来越多的行 但发送之间没有固定的时间 现在我的问
  • 在 XMLDocument 中使用 DocumentElement 时发生访问冲突

    当我尝试使用时 我总是遇到访问冲突DocumentElement of the XMLDocument 我创造XMLDocument基于某些文件的存在 错误信息 项目project1 exe引发异常类EAccessViolation 消息
  • 在该对象调用的事件期间销毁该对象

    我有一个按钮 它的 OnClick 事件调用一个销毁按钮的过程 但随后 线程 想要返回到 OnClick 事件 并且我遇到了访问冲突 我完全被难住了 您需要在按钮的所有代码执行完毕后销毁该按钮 执行此操作的标准方法是将用户定义的消息发布到表
  • Delphi中AsInteger和Value有什么区别?

    我想知道以下两个与delphi中的数据集相关的语句之间的区别 dsMyDataSet ParamByName ID AsInteger 1122 If ID is integer dsMyDataSet ParamByName ID AsS
  • delphi专家中的第三方依赖

    我正在编写一个delphi ide Expert 带有一些第三方依赖项 视觉控件 我的问题是当这个专家将安装在目标机器上时 这台电脑是否也需要安装这些第三方组件 或者组件是embeded在生成的 bpl 内部 它们将依赖于您放置在包的 re
  • 使用 Inno Setup 中格式化(部分粗体)的文本制作安装程序?

    有人看过 GOG com 游戏安装程序吗 如何制作像这样的欢迎文本字符串 包括单个标题中的路径和需要大小 其中部分内容加粗 以下是修改安装路径后如何更改字符串换行的示例 您可以使用TRichEditViewer http www jrsof
  • Delphi XE 和 OmniXML:使用 SelectNode()?

    我将以下 XML 片段作为一个更大的 XML 文件的一部分 我正在使用最新的 OmniXML 快照进行处理
  • 为什么使用过程来创建对象比使用函数更受欢迎?

    这类似于这个问题 https stackoverflow com questions 1894217 is it memory safe to provide an object as a function result 我问 为什么 到最
  • TRichEdit和URL高亮问题

    我正在使用当前代码在 TRichEdit 上突出显示 URL procedure TForm1 WndProc var Message TMessage var p TENLink strURL string begin if Messag
  • 使用 gmail 和 Indy 发送电子邮件

    我正在尝试使用 gmail 从 Delphi 发送电子邮件 我有 Indy 10 5 9 0 和 Delphi XE3 我从以下位置获得了示例代码 http www andrecelestino com delphi xe envio de
  • 如何解决内存分段并强制FastMM释放内存给OS?

    注意 32 位应用程序不计划迁移到 64 位 我正在使用一个非常消耗内存的应用程序 并且几乎优化了与内存分配 取消分配相关的所有相关路径 应用程序本身没有内存泄漏 没有句柄泄漏 没有任何其他类型的泄漏 据我所知并经过测试 我无法触及的第 3
  • Delphi - 如何将通用参数传递给接受 const 参数数组的函数

    我有一个 基类 其中包含一个 函数 该函数接受 const 数组 类型的参数 如下所示 type TBaseClass class TObject public procedure NotifyAll const AParams array
  • XE2 中的 COM 是否损坏?我该如何解决它?

    Update XE2 Update 2 修复了下述错误 下面的程序是从实际程序中截取的 在 XE2 中失败并出现异常 这是 2010 年的回归 我没有 XE 来测试 但我希望该程序在 XE 上运行良好 感谢 Primo 确认代码在 XE 上
  • Delphi 7,加载PNG到TImage

    只是想加载 PNG 尝试使用适用于其他格式的 OleGraphic 来使用我的 LoadPic 但在 PNG 上失败 目标是将图像复制到隐藏位图 然后将其屏蔽并复制到可见的工作图像画布 如果 CopyRect 不这样做 请随意提出其他建议

随机推荐

  • Qt::BackgroundRole 似乎被忽略

    我正在使用源自的自定义表格模型QAbstractTableModel 我已经覆盖了headerData 我可以通过返回颜色来更改单个行标题 或列标题 但我在这里只讨论行 的字体颜色Qt ForegroundRole if role Qt F
  • Java Swing:JScrollPane 不工作

    我有一个包含一些字段的 JPanel JPanel 的高度有限 因此我必须在它周围放置一个 JScrollPane 以便人们可以向下滚动 正如您在下面看到的 它显示得非常完美 但您无法向下 或向上 滚动 DetailPanel detail
  • 如何在 Azure AD 身份验证后重定向到 ASP Net Core MVC 中的不同控制器操作

    我已将 ASP Net Core 2 0 项目设置为使用 Azure AD 进行身份验证 使用 VS2017 中使用 OIDC 的标准 Azure AD 身份验证模板 一切工作正常 应用程序返回到基本 url 并在身份验证成功后运行 Hom
  • 如何让 Hadoop 使用我系统上的所有核心?

    我有一个32核的系统 当我使用 Hadoop 运行 MapReduce 作业时 我从未看到 java 进程使用超过 150 CPU 根据 top 并且通常保持在 100 左右 它应该接近 3200 我需要更改哪些属性 以及在哪个文件中 才能
  • 将自定义 Soap 标头添加到 Web 服务请求

    我已经使用 apache axis2 为 Web 服务生成了存根 并且我想将自定义肥皂头添加到请求中 我希望肥皂头看起来像这样
  • OpsHub 迁移似乎不再正常运行

    大约一个月前 我对一些本地 TFS 项目到在线 Visual Studio 进行了测试迁移 在大多数情况下 一切都有效 变更集已迁移 显示与本地相同的签入用户 并带有显示原始签入日期 用户和变更集 ID 的注释 与工作项相同 我会查看历史记
  • 在 NumPy 或 PyTorch 中从矩阵获取对角线“条纹”

    我需要获得矩阵的对角线 条纹 假设我有一个大小为 KxN K gt N 的矩阵 0 1 2 3 4 5 6 7 8 9 10 11 我需要从中提取一条对角线条纹 在本例中 是通过截断原始矩阵创建的矩阵 MxV 大小 0 x x 3 4 x
  • Kubernetes Ingress - 第二个节点端口没有响应

    我在本地运行 K8S 集群 云中没有 有一个 K8S 主节点和两个工作节点 k8s master 192 168 100 100 工作节点1 192 168 100 101 工作节点2 192 168 100 102 我使用 kuberne
  • 为什么截断 BytesIO 会弄乱它?

    在 OSX 上的 Python 3 5 1 上运行 import io b io BytesIO b write b 222 print b getvalue b truncate 0 b write b 222 print b getva
  • 如何防止在 Objective-C 中使用除我的自定义方法之外的其他 init 方法

    背景 在我的 iPhone 应用程序中 我有一个自定义 UITableViewController 我打算通过将现有的 id initWithStyle UITableViewStyle style 方法扩展为扩展的自定义方法来向其传递一些
  • 具有固定标题和全页宽度网格的 Gridview

    我之前问过问题在 gridview 中冻结标题时正确设置标题宽度和列通过使用这些解决方案 我发现分辨率存在一些问题 因此我在设计本身中添加了所有列 但是当列具有大长度文本时 我仍然面临问题 我正在尝试使用此中给出的代码冻结 Gridview
  • 频域中的 Gabor 滤波器实现

    Here我们有 Gabor 滤波器的空间域实现 但是 我需要在频域中实现 Gabor 滤波器出于性能原因 我已经找到了Gabor滤波器的频域方程 I am actually in doubt about the correctness an
  • 将字符串属性绑定到对象

    假设我有一堂这样的课 public class MyClass public string Name public int Id public override string ToString return this Id ToString
  • 如何使用QTcpSocket监听qt中的特定端口? [复制]

    这个问题在这里已经有答案了 我正在使用 QTcpSocket 在两个应用程序之间进行通信 一个是C 程序 另一个是用PHP编写的网页 目标是使用套接字将数据从我的网页发送到我的 C 程序 我不知道如何在特定端口 例如 12345 上打开连接
  • 为 Git 存储库自定义 CSH 提示

    当我在 Git 存储库中时 我希望有一个自定义 CSH 提示 如果我不在 git 存储库中 我希望提示符看起来像这样 host name gt 但是当我进入 Git 存储库时必须变成这样 host name GIT REPO ROOT DI
  • 禁用 Jackson 中的数字到字符串自动转换

    当我向 Spring Boot 后端发出 json 请求时 Jackson 会自动将数字转换为字符串 有办法防止这种情况吗 例如 JSON numberAsString 123 JAVA private String numberAsStr
  • scala 应用程序中找不到对象播放

    我正在使用Eclipse并创建一个新的Scala对象 想要使用play的json解析功能并导入此包 但出现错误object play无法找到 想知道如何在 Scala 对象中使用 play 库 这就是我导入的方式 import play a
  • 无法在node.js中使用mongoose查询mongoDB

    假设我的 mongoDB 中有一个集合 db co并且只有一个文档 id ObjectId 50d083e32cdcf7ce065b616c age 22 friends Tom location NY name lee skill jav
  • jQuery.validate 插件和 ajax 表单提交

    我一生都无法让它发挥作用 验证错误看起来很好 我没有收到语法错误 但什么也没有发生 表单只是提交到页面 我也无法获得成功或错误警报
  • 方法指针的 RTTI 信息

    是否可以获取有关某个设备的 RTTI 信息TMethod 我可以通过以下方式获取实例 Instance TObject Method Data 这样我就可以获得实例的RTTI类型 但是如何才能获得正确的TRttiMethod 我想检查使用方