【问题标题】:Delphi pointer casting德尔福指针铸造
【发布时间】:2014-07-14 07:45:29
【问题描述】:

我想在 delphi 中使用这个简单的 C 函数,但不能完美地将值转换为指针。

C 函数:

PVOID GetInterfaceMethod(PVOID intf, DWORD methodIndex)
{
  return *(PVOID*)(*(DWORD_PTR*)intf + methodIndex);
}

德尔福函数:

function GetInterfaceMethod(const intf; methodIndex: DWORD): Pointer;
begin
  // return *(PVOID*)(*(DWORD_PTR*)intf + methodIndex);    x64
  // return *(PVOID*)(*(DWORD*)intf + methodIndex * 4);    x86
  Result := Pointer(Pointer(DWORD_PTR(Pointer(intf)^) + methodIndex)^);  //x64
end;

对不起,我的英语不好。

【问题讨论】:

  • 在查看 x86 实现(Delphi 例程中的注释代码)时,x64 实现显然是错误的。因此,有问题的 C 函数一开始可能是错误的(如果应该乘以 8)。这也是有道理的,因为参数被称为 methodIndex 而不是 byteOffset 或类似的东西,然后由架构依赖于调用方。
  • return *(PVOID*)(*(DWORD_PTR*)intf + methodIndex*sizeof(PVOID)); 可以在任何地方使用,尽管这样做会很蹩脚。

标签: c delphi pointers casting


【解决方案1】:

这不是 C 代码的 100% 翻译,但它可以通过使用此方法完成您尝试实现的目标:

  function GetInterfaceMethod(const intf; methodIndex: Cardinal): Pointer;
  type
    PPVtable = ^PVtable;
    PVtable = ^TVtable;
    TVtable = array[0..MaxInt div SizeOf(Pointer) - 1] of Pointer;
  begin
    Result := PPVtable(intf)^^[methodIndex];
  end;

这段代码说明了接口引用是指向 IMT 的指针,如下所示:

【讨论】:

    【解决方案2】:
    PVOID GetInterfaceMethod(PVOID intf, DWORD methodIndex)
    {
      return *(PVOID*)(*(DWORD_PTR*)intf + methodIndex);
    }
    

    要对此进行解码,我们需要了解C++ operator precedence。这里的最高优先级运算符是类型转换。然后取消引用高于二进制加法。因此,加上括号,表达式变为:

    *(PVOID*)((*(DWORD_PTR*)intf) + methodIndex)
    

    即:

    • intf 转换为指向DWORD_PTR 的指针,
    • 取消对DWORD_PTR的引用,
    • 添加方法索引,
    • 转换为指向PVOID的指针,
    • 取消引用。

    请注意,这个函数很奇怪,因为methodIndex 是字节偏移量而不是数组索引。充其量参数名称非常具有误导性。在最坏的情况下,它会使函数非常难以使用,特别是如果您想要独立于指针大小工作的代码。因此,如果此功能真的是解决您实际面临的任何问题的最佳方法,我会感到惊讶。

    直译是这样的:

    function GetInterfaceMethod(intf: Pointer; byteOffset: DWORD): Pointer;
    begin
      Result := PPointer(PDWORD_PTR(intf)^ + byteOffset)^;
    end;
    

    您可能更喜欢编写此代码,其中methodIndex 是数组索引而不是字节偏移量。那会更有意义。 C 代码将是:

    PVOID GetInterfaceMethod(PVOID intf, DWORD methodIndex)
    {
        return *(*(PVOID**)intf + methodIndex);
    }
    

    以及匹配的Delphi代码:

    {$POINTERMATH ON}
    function GetInterfaceMethod(intf: Pointer; methodIndex: DWORD): Pointer;
    begin
      Result := (PPointer(intf^) + methodIndex)^;
    end;
    

    请仔细注意,此函数的行为与上面的完全不同,因为methodIndex 被解释为数组索引。所以,这个函数不是问题中C代码的翻译。

    【讨论】:

      猜你喜欢
      • 2013-01-15
      • 2014-07-08
      • 1970-01-01
      • 2014-12-19
      • 1970-01-01
      • 1970-01-01
      • 2011-04-03
      • 2010-12-27
      • 1970-01-01
      相关资源
      最近更新 更多