如何将RETRIEVAL_POINTERS_BUFFER结构转换为Delphi?

时间:2012-10-06 20:25:42

标签: delphi winapi struct delphi-xe2 code-conversion

我正在使用Windows API,并且必须在Delphi record中重新创建a structure。我想我已经把它弄下来,但这个有点令人困惑,我需要确保我做对了。

这是原始的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;

请注意,此结构中有一个数组结构。这是我迷路的地方。如果我没弄错的话,Delphi版应该是这样的:

  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中使用此结构时,它似乎确实有效。但是,由于结构中的这个结构数组,我有点犹豫,我正确地做到了这一点。这看起来不错吗?

3 个答案:

答案 0 :(得分:6)

Extents字段是结构中内联的可变长度数组。实际的结构将具有ExtentCount个元素。你不能在这里使用Delphi动态数组。事实上,你永远不能在互操作中使用Delphi动态数组。

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

对于整数类型,请将C中的DWORD映射到Delphi中的DWORD。在Delphi中,LARGE_INTEGER在C中LARGE_INTEGER。这些都与Delphi 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分配,那么你可以如上所述。

答案 1 :(得分:2)

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

这个C声明很奇怪,因为它声明为只有一个元素的数组。如果你想要完全复制它,你应该将它声明为array [0..0] of TExtent

答案 2 :(得分: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访问此结构。

希望这有帮助。