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