如何将检索指针缓冲区结构转换为Delphi?

如何将检索指针缓冲区结构转换为Delphi?,delphi,winapi,struct,delphi-xe2,code-conversion,Delphi,Winapi,Struct,Delphi Xe2,Code Conversion,我正在使用Windows API,必须在Delphi记录中重新创建。我想我已经记下来了,但是这一次有点混乱,我需要确保我做得对 这里是原来的C++结构: typedef struct RETRIEVAL_POINTERS_BUFFER { DWORD ExtentCount; LARGE_INTEGER StartingVcn; struct { LARGE_INTEGER NextVcn; LARGE_INTEGER Lcn; } Extents

我正在使用Windows API,必须在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;
请注意,此结构中有一个数组结构。这就是我迷路的地方。如果我没有弄错的话,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中使用此结构时,它似乎确实起作用。但是,由于结构内部的这个结构数组,我有点犹豫我是否正确地做了这件事。这看起来正确吗?

文本项定义为
文本项数组是错误的。这将它声明为动态数组,一种托管引用类型。您需要的是一个有界数组,如text的
数组[x..y]


这个C声明相当奇怪,因为它被声明为一个只有一个元素的数组。如果要精确复制它,应该将其声明为text的
数组[0..0]

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

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

对于整型,请将C中的
DWORD
映射到Delphi中的
DWORD
。C中的
LARGE\u INTEGER
到Delphi中的
LARGE\u 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\u INTEGER
类型很难使用。您可能更愿意将这些字段声明为
Int64



这种类型的结构总是由堆分配的。堆分配代码必须计算出适合可变长度数组中
ElementCount
项所需的大小。如果要分配缓冲区,则需要单独定义类型的内部记录,以便可以方便地将其命名为传递给
SizeOf
。如果API进行分配,则您可以如上所述。

启动VCN、NextVcn和Lcn定义为大整数,在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 = record
  case Integer of
    0: ( LowPart: DWORD;
      HighPart: Longint; );
    1: ( QuadPart: LONGLONG);
end;
龙龙实际上只是一个Int64。您可以使用LowPart和Highpart或QuadPart访问此结构


希望这能有所帮助。

几乎所有内容都已翻译。@TLama,我想这可能就是我的答案,只要“几乎”不是一个因素。我指的是Windows API中的几乎所有内容。这是一个可变长度的数组。但你不能这样声明。实际数组具有ExtentCount元素。+1,特别是对于您的编辑。我几乎总是给内部记录一个单独定义的类型。它使很多事情变得非常简单。随着记录方法的引入,我会在
TRetrievalPointersBuffer
类型上添加一个方法,用于计算给定
ExtentCount
@jeroen的总大小。在这个方法中,我会在外部记录中定义内部类型。当您知道数组的上限时,可以通过相应地声明数组将其放入堆栈中。不是针对这种特定情况,但是假设您有
WCHAR Name[1]
,并且您知道它最多包含255个字符,那么您可以将该字段定义为
Name:WCHAR[0..254]
。我将尝试重新说明-1。。。您可能知道元素的最大可能数量,或者您可能不关心实际信息,而只想知道元素的数量,或者您可能只关心元素计数小于定义总数时的信息。声明这种结构的数组元素的数量大于1,并因此将其放在堆栈中,这没有什么错。这不是api的问题,因为接受这种结构的api对传递的大小是否符合api头不感兴趣,而对实际使用的缓冲区大小不感兴趣。@Sertac在这种情况下,当遇到更多错误数据时,您可能会使用堆栈分配并反复调用。不过我还是会的。