2012-10-06 112 views
2

我正在使用Windows API并必须在Delphi record内重新创建a structure。我想我已经记下了,但是这个有点令人困惑,我需要确保我做对了。如何将RETRIEVAL_POINTERS_BUFFER结构转换为Delphi?

这里的原有C++结构:

typedef struct RETRIEVAL_POINTERS_BUFFER { 
    DWORD   ExtentCount; 
    LARGE_INTEGER StartingVcn; 
    struct { 
    LARGE_INTEGER NextVcn; 
    LARGE_INTEGER Lcn; 
    } Extents[1]; 
} RETRIEVAL_POINTERS_BUFFER, *PRETRIEVAL_POINTERS_BUFFER; 

注意,有此结构内的阵列结构。这是我迷路的地方。如果我没有记错的话,德尔福版本应该是这样的:

TExtent = record 
    NextVcn: Integer; 
    Lcn: Integer; 
    end; 

    TExtents = array of TExtent; 

    PRETRIEVAL_POINTERS_BUFFER = ^TRETRIEVAL_POINTERS_BUFFER; 
    TRETRIEVAL_POINTERS_BUFFER = record 
    ExtentCount: DWORD; 
    StartingVcn: Integer; 
    Extents: TExtents; 
    end; 

当我在Windows API中使用这样的结构,它似乎工作。但是,由于结构内部有这个结构数组,所以我有点犹豫,我做了这个正确的。这看起来正确吗?

+4

几乎所有的东西都已经翻译过了['JEDI'](http://www.koders.com/delphi/fid87C50F65617654141B73DFD6DAF36BC0B953BF75.aspx)。 – TLama

+0

@TLama,只要“几乎”不是一个因素,我认为这可能是我的答案。 –

+3

我的意思是几乎所有的Windows API。你需要什么[当然完成](http://www.koders.com/delphi/fid87C50F65617654141B73DFD6DAF36BC0B953BF75.aspx#L3913)。 – TLama

回答

6

Extents字段是内嵌在结构中的可变长度数组。实际的结构将有ExtentCount元素。你不能在这里使用Delphi动态数组。事实上,你绝对不能在interop中使用Delphi动态数组。

因此,像C代码那样声明它为array [0..0]。为了访问它,你需要禁用范围检查。该记录的实际实例将在索引0..ExtentCount-1中具有有效数据。

对于您的整体类型,在德尔福地图DWORD在C到DWORD。并且在Delphi中使用LARGE_INTEGER的C到LARGE_INTEGER。这些都不是德尔福Integer相同。前者是无符号的,后者是64位宽。

PRetrievalPointersBuffer = ^TRetrievalPointersBuffer; 
TRetrievalPointersBuffer = record 
    ExtentCount: DWORD; 
    StartingVcn: LARGE_INTEGER; 
    Extents: array [0..0] of record 
    NextVcn: LARGE_INTEGER; 
    Lcn: LARGE_INTEGER; 
    end; 
end; 

LARGE_INTEGER类型是相当尴尬的工作。您可能更愿意将这些字段声明为Int64


这种类型的结构是不变的堆分配。堆分配代码必须计算出适合于可变长度数组中的ElementCount项所需的大小。如果您正在分配缓冲区,那么您将需要单独定义类型的内部记录,以便您方便地将其命名为SizeOf。如果API分配,那么你就像上面那样好。

+0

+1,尤其适合您的编辑。我几乎总是给内部记录一个单独定义的类型。它使很多事情变得非常简单。随着记录方法的引入,我会在'TRetrievalPointersBuffer'类型上添加一个方法,用于计算给定'ExtentCount'的总大小。 –

+1

@jeroen在这是我定义外部记录内的内部类型。 –

+0

当您知道数组的上界时,您可以通过相应地声明数组来使其位于堆栈中。不是这个特定的情况,但是假设你有'WCHAR Name [1]',并且你知道它至多有255个字符,那么你可以将该字段定义为'Name:WCHAR [0..254]'。 –

2

TExtents定义为array of TExtent是一个错误。这是声明它作为一个动态数组,一个托管参考类型。你需要的是一个有界的数组,如array [x..y] of TExtent

这个C声明很奇怪,但它声明为只有一个元素的数组。如果您想精确复制它,则应声明它为array [0..0] of TExtent

+0

它是一个可变长度数组。但是你不能这样宣布。实际的数组有ExtentCount元素。 –

2

StartingVcn,NextVcn和LCN被定义为LARGE_INTEGER这是在WINNT.H定义如下:

typedef union _LARGE_INTEGER { 
    struct { 
     DWORD LowPart; 
     LONG HighPart; 
    } DUMMYSTRUCTNAME; 
    struct { 
     DWORD LowPart; 
     LONG HighPart; 
    } u; 
    LONGLONG QuadPart; 
} LARGE_INTEGER; 

根据您所使用的Delphi的版本,你所定义的结构可能无法正常工作。 LARGE_INTEGER应声明如下:

LARGE_INTEGER = record 
    case Integer of 
    0: (LowPart: DWORD; 
     HighPart: Longint;); 
    1: (QuadPart: LONGLONG); 
end; 

LONGLONG实际上只是一个Int64。您可以使用LowPart和Highpart或QuadPart访问此结构。

希望这会有所帮助。

+3

LARGE_INTEGER已经在Windows.pas中定义。 –