2014-07-14 22 views
3

我想在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; 

对不起我的英语不好。

+0

在查看x86实现(Delphi例程中的注释代码)时,x64实现显然是错误的。所以C函数可能是错误的(如果乘以8)。这也是有道理的,因为参数被称为methodIndex而不是byteOffset,或者类似于依赖于调用方的体系结构。 –

+1

'return *(PVOID *)(*(DWORD_PTR *)intf + methodIndex * sizeof(PVOID));'可以在任何地方工作,尽管这样做可能是一种非常蹩脚的方式。 –

回答

8

这不是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如下所示:

enter image description here

1
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
  • 添加methodIndex,
  • 投向指向PVOID
  • de参考。

请注意,这个函数很奇怪,因为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代码的翻译。