Delphi指针类型转换

3
我想在Delphi中使用这个简单的C函数,但无法完美地将值转换为指针。
C函数:
PVOID GetInterfaceMethod(PVOID intf, DWORD methodIndex)
{
  return *(PVOID*)(*(DWORD_PTR*)intf + methodIndex);
}

Delphi函数:
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;

对不起,我的英语不好。

当查看 Delphi 例程中的注释代码时,x64 实现显然是错误的。因此,涉及的 C 函数可能一开始就是错误的(如果应该乘以 8)。这也是有道理的,因为该参数称为 methodIndex 而不是 byteOffset 或类似依赖于调用方的体系结构。 - Stefan Glienke
1
return *(PVOID*)(*(DWORD_PTR*)intf + methodIndex*sizeof(PVOID)); 这样做虽然可行,但是这是一种相当糟糕的方式。 - David Heffernan
2个回答

7
这不是C代码的百分之百翻译,但可以通过使用这种方法实现您想要达到的目的。
  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的指针,如下所示:

enter image description here


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

要解码这个,我们需要了解C++运算符优先级。这里最高优先级的运算符是类型转换。然后解引用比二进制加法更高。因此,加上括号后表达式变成:

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

即:

  • intf转换为指向DWORD_PTR的指针,
  • 解引用它,得到DWORD_PTR
  • 加上methodIndex
  • 将其转换为指向PVOID的指针,
  • 再次解引用。

请注意,这个函数非常奇怪,因为methodIndex是一个字节偏移量,而不是数组索引。最好的情况下,参数名非常误导人。最糟糕的情况下,这使得函数非常难以使用,特别是如果你想编写能够独立于指针大小工作的代码。因此,如果您实际面临的问题有更好的解决方法,我会感到惊讶。

直译如下:

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

你可能更喜欢使用数组索引而不是字节偏移量来编写此代码。这样会更有意义。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代码的翻译。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接