RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 656699
Accepted
Pax Beach
Pax Beach
Asked:2020-04-21 20:43:16 +0000 UTC2020-04-21 20:43:16 +0000 UTC 2020-04-21 20:43:16 +0000 UTC

Delphi中如何获取偏移地址或接口方法指针

  • 772

我有一个指向 IDirect3DDevice9 接口的指针,它有 119 个方法(包括 3 个标准方法)在 d3d9.dll 中实现。

我需要在我的 Delphi 代码中获取接口方法 EndScene() 和 Present() 相对于库开头(指向 DLL 的指针)的偏移量(以字节为单位)。

var:
    g_pD3DDevice: IDirect3DDevice9;
    ProcAddr: Pointer;
    hD3D9: HMODULE;
    Present9 : DWORD;
    EndScene9: DWORD;

implemenation:
    hD3D9 := LoadLibrary('d3d9');
    ProcAddr := GetProcAddress(hD3D9, 'Direct3DCreate9');
    ...
    pD3D.CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, TargetHandle, D3DCREATE_SOFTWARE_VERTEXPROCESSING, @D3DPP, g_pD3DDevice);

我假设在 VMT 中 Present() 方法排在第 17 位(从 0 开始),而 EndScene() 排在第 42 位,因为它写在 d3d9.dll 头文件中。

但我认为像这样计算偏移量不是一个好主意:

Present9 := DWORD(g_pD3DDevice) + (17 * 4) - DWORD(hD3D9);
EndScene9 := DWORD(g_pD3DDevice) + (42 * 4) - DWORD(hD3D9);

请告诉我这个问题的最佳解决方案!

delphi
  • 2 2 个回答
  • 10 Views

2 个回答

  • Voted
  1. Best Answer
    Pax Beach
    2020-04-23T06:14:46Z2020-04-23T06:14:46Z

    这个解决方案是在网上找到的。

    一个示例实现是:

    1)我声明所需方法的过程类型

    type
      TPresent9 = function(pSourceRect, pDestRect: PRect; hDestWindowOverride: HWND; pDirtyRegion: PRgnData): HResult of object; stdcall;
    

    2)我声明了一个这种类型的变量

    var
      PPresent: TPresent9;
    begin
      ...
      IntRefToMethPtr(d3d9Dev, PPresent, 17);
      PPresent(nil, nil, DParametrs.D3DPP.hDeviceWindow, nil);
    

    3)我实现了通过编号获取接口方法的过程

    procedure IntRefToMethPtr(const IntRef; var MethPtr; MethNo: Integer);
    type
      TVtable  = array [0 .. 999] of Pointer;
      PVtable  = ^TVtable;
      PPVtable = ^PVtable;
    begin
      // QI=0, AddRef=1, Release=2, etc
      TMethod(MethPtr).Code := PPVtable(IntRef)^^[MethNo];
      TMethod(MethPtr).Data := Pointer(IntRef);
    end;
    

    4)现在我们通过序号获取接口方法并调用它

      IntRefToMethPtr(d3d9Dev, PPresent, 17);
      PPresent(nil, nil, DParametrs.D3DPP.hDeviceWindow, nil);
    
    • 3
  2. zed
    2020-04-23T19:40:43Z2020-04-23T19:40:43Z

    接口类型变量是指向Interface Method Table (IMT)-接口方法表的指针,其中包含指向相应方法代码的指针:

    虚拟机

    Delphi 有一个特殊的汇编程序指令 - VMTOFFSET,它允许您获取虚拟方法地址相对于虚拟方法表 (VMT) 开头的偏移量(以字节为单位)

    VMTOFFSET 从虚拟方法表 (VMT) 的开头检索虚拟方法参数的虚拟方法指针表条目的偏移量(以字节为单位)。该指令需要一个完整指定的类名和一个方法名作为参数(例如,TExample.VirtualMethod),或者一个接口名和一个接口方法名。

    http://docwiki.embarcadero.com/RADStudio/Tokyo/en/Assembler_Syntax

    因此,知道我们需要的方法的名称,我们可以获得指向其代码的指针:

    function GetPresentMethodPointer(const IntRef: IInterface): Pointer; assembler;
    asm
      mov eax, [IntRef] 
      add eax, vmtoffset IDirect3DDevice9.Present
      mov eax, [eax]
    end;
    
    var
      VD3Dev: IDirect3DDevice9;
      VPresentCodePtr: Pointer;
    begin
      ... 
      // создание экземпляра VD3Dev
      ...
      VPresentCodePtr := GetPresentMethodPointer(VD3Dev);
      ...
    

    也没有必要计算方法的序数。

    • 1

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    Python 3.6 - 安装 MySQL (Windows)

    • 1 个回答
  • Marko Smith

    C++ 编写程序“计算单个岛屿”。填充一个二维数组 12x12 0 和 1

    • 2 个回答
  • Marko Smith

    返回指针的函数

    • 1 个回答
  • Marko Smith

    我使用 django 管理面板添加图像,但它没有显示

    • 1 个回答
  • Marko Smith

    这些条目是什么意思,它们的完整等效项是什么样的

    • 2 个回答
  • Marko Smith

    浏览器仍然缓存文件数据

    • 1 个回答
  • Marko Smith

    在 Excel VBA 中激活工作表的问题

    • 3 个回答
  • Marko Smith

    为什么内置类型中包含复数而小数不包含?

    • 2 个回答
  • Marko Smith

    获得唯一途径

    • 3 个回答
  • Marko Smith

    告诉我一个像幻灯片一样创建滚动的库

    • 1 个回答
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Алексей Шиманский 如何以及通过什么方式来查找 Javascript 代码中的错误? 2020-08-03 00:21:37 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    user207618 Codegolf——组合选择算法的实现 2020-10-23 18:46:29 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5