如何将RETRIEVAL_POINTERS_BUFFER结构转换为Delphi?

Jer*_*dge 2 delphi winapi struct code-conversion delphi-xe2

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

这是原始的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;
Run Code Online (Sandbox Code Playgroud)

请注意,此结构中有一个数组结构.这是我迷路的地方.如果我没弄错的话,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;
Run Code Online (Sandbox Code Playgroud)

当我在Windows API中使用此结构时,它似乎确实有效.但是,由于结构内部的这个结构数组,我有点犹豫,我正确地做到了这一点.这看起来不错吗?

Dav*_*nan 6

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

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

对于您的整数类型,请DWORD在C 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;
Run Code Online (Sandbox Code Playgroud)

这种LARGE_INTEGER类型很难处理.您可能更愿意将这些字段声明为Int64.


这种类型的结构总是堆分配的.堆分配代码必须计算出适合ElementCount可变长度数组中项目所需的大小.如果要分配缓冲区,则需要在单独定义的类型中使用内部记录,以便您可以方便地将其命名为传递给它SizeOf.如果API分配,那么你就可以了.