11
typedef struct _FILE_OBJECTID_INFORMATION {
    LONGLONG FileReference;
    UCHAR ObjectId[16];
    union {
        struct {
            UCHAR BirthVolumeId[16];
            UCHAR BirthObjectId[16];
            UCHAR DomainId[16];
        } DUMMYSTRUCTNAME;
        UCHAR ExtendedInfo[48];
    } DUMMYUNIONNAME;
} FILE_OBJECTID_INFORMATION, *PFILE_OBJECTID_INFORMATION;

如何将这样的联合翻译成德尔福?

4

2 回答 2

25

C 的 Pascal 等效项union称为变体记录

一个记录类型可以有一个变体部分,它看起来像一个case 语句。变体部分必须跟在记录声明中的其他字段之后。

要声明具有变体部分的记录类型,请使用以下语法:

type recordTypeName = record
  fieldList1: type1;
   ...
  fieldListn: typen;
case tag: ordinalType of
  constantList1: (variant1);
   ...
  constantListn: (variantn);
end;

声明的第一部分——直到保留字大小写——与标准记录类型的相同。声明的其余部分——从大小写到可选的最后分号——称为变体部分。在变体部分,

  • tag是可选的,可以是任何有效的标识符。如果省略tag,则也省略其后的冒号 (:)。
  • ordinalType表示序数类型。
  • 每个constantList是一个常量,表示类型为ordinalType的值,或以逗号分隔的此类常量列表。在组合的constantLists中不能多次表示任何值。
  • 每个变体都是一个以分号分隔的声明列表,类似于fieldList:记录类型主要部分中的类型构造。也就是说,变体具有以下形式:

    字段列表1:类型1;... 字段列表:类型;

其中每个fieldList是一个有效的标识符或以逗号分隔的标识符列表,每个类型表示一个类型,最后的分号是可选的。类型不能是长字符串、动态数组、变体(即Variant类型)或接口,也不能是包含长字符串、动态数组、变体或接口的结构化类型;但它们可以是指向这些类型的指针。

具有变体部分的记录在语法上很复杂,但在语义上却看似简单。记录的变体部分包含多个变体,它们共享内存中的相同空间。您可以随时读取或写入任何变体的任何字段;但是,如果您先写入一个变体中的字段,然后再写入另一个变体中的字段,则可能会覆盖您自己的数据。该标签(如果有的话)作为记录的非变体部分中的一个额外字段(类型为ordinalType )。


至于其余的,这很常规:LONGLONG是一个 64 位整数,并且UCHARunsigned char, 或AnsiChar在 Delphi 中。

type
  TFileObjectIDInformation = record
    FileReference: Int64;
    ObjectID: array[0..15] of AnsiChar;
    case Integer of
    0:
      (
        BirthVolumeId: array[0..15] of AnsiChar;
        BirthObjectId: array[0..15] of AnsiChar;
        DomainId: array[0..15] of AnsiChar;
      );
    1:
      (ExtendedInfo: array[0..47] of AnsiChar);
  end;

可能Byte比 更合适AnsiChar。当然,这有点难说,因为 C 与 Pascal 不同,没有单独的类型ByteAnsiChar。但是这些数组在我看来好像它们会被当作文本来阅读,所以我的猜测是这AnsiChar会更合适。

于 2012-11-10T17:46:43.453 回答
5

类似的结构可以在JEDI API Lib中找到:

  _FILE_OBJECTID_BUFFER = record

    //
    //  This is the portion of the object id that is indexed.
    //

    ObjectId: array [0..15] of BYTE;

    //
    //  This portion of the object id is not indexed, it's just
    //  some metadata for the user's benefit.
    //

    case Integer of
      0: (
        BirthVolumeId: array [0..15] of BYTE;
        BirthObjectId: array [0..15] of BYTE;
        DomainId: array [0..15] of BYTE);
      1: (
        ExtendedInfo: array [0..47] of BYTE);
  end;
于 2012-11-10T17:50:45.540 回答