我正在为一个delphi单元转换一个C头。我对UNION表示怀疑。 例如,在下面的示例中,应用的逻辑是什么(CASE INTEGER OF)? 这是转换此结构的正确方法吗?
在C
typedef union _FLT_PARAMETERS {
struct {
PIO_SECURITY_CONTEXT SecurityContext;
ULONG Options;
USHORT POINTER_ALIGNMENT FileAttributes;
USHORT ShareAccess;
ULONG POINTER_ALIGNMENT EaLength;
PVOID EaBuffer;
LARGE_INTEGER AllocationSize;
} Create;
struct {
PIO_SECURITY_CONTEXT SecurityContext;
ULONG Options;
USHORT POINTER_ALIGNMENT Reserved;
USHORT ShareAccess;
PVOID Parameters; // PNAMED_PIPE_CREATE_PARAMETERS
} CreatePipe;
...
在Delphi中
TCreate = record
SecurityContext: PIO_SECURITY_CONTEXT;
Options: ULONG;
FileAttributes: USHORT;
ShareAccess: USHORT;
EaLength: ULONG;
EaBuffer: PVOID;
AllocationSize: LARGE_INTEGER;
end;
TCreatePipe = Record
SecurityContext: PIO_SECURITY_CONTEXT;
Options: ULONG;
Reserved: USHORT;
ShareAccess: USHORT;
Parameters: PVOID;
end;
_FLT_PARAMETERS = Record
case integer of
0: (Create: TCreate);
1: (CreatePipe: TCreatePipe):
...
答案 0 :(得分:4)
这是转换此结构的正确方法吗?
工会正确翻译。您的Pascal变体记录是处理联合的正确方法。记录的变体部分与C联合处理相同。来自documentation:
带有变体部分的记录在语法上很复杂,但在语义上看起来很简单。记录的变体部分包含几个在内存中共享相同空间的变体。您可以随时读取或写入任何变体的任何字段;但如果您在一个变体中写入某个字段,然后在另一个变体中写入某个字段,则可能会覆盖您自己的数据。
我可以在代码中看到的唯一问题是宏POINTER_ALIGNMENT
。那个宏扩展到了什么?我的期望是,对于32位代码,它将扩展到__declspec(align(4))
,对于64位代码,它将扩展到__declspec(align(8))
。
假设猜测是正确的,那么在编译32位时,您的Delphi代码已经具有正确的布局。这是因为标有POINTER_ALIGNMENT
的每个字段都已经放在4字节边界上。
但是对于64位,记录将无法正确布局。如果您要定位64位,则必须添加一些额外的填充,因为标有POINTER_ALIGNMENT
的每个成员都将被错误地布局。不幸的是,Delphi中没有__declspec(align(#))
的等价物,所以你需要手动添加填充。
如果你确实需要添加这个填充,你应该仔细检查C和Delphi版本是否具有相同的布局。检查每个字段的偏移是否匹配。