Как перевести C-соединение в Delphi?

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;

Как перевести такой союз на Delphi?

Ответ 1

Эквивалент Pascal C union известен как вариантная запись.

Тип записи может иметь вариантную часть, которая выглядит как caseвыражение. Вариантная часть должна следовать за другими полями в записи декларация.

Чтобы объявить тип записи с помощью варианта, используйте следующие Синтаксис:

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

Первая часть объявления - до зарезервированного слова case - является такой же, как у стандартного типа записи. Остальная часть объявление - от case к необязательной конечной точке с запятой - вызывается вариант. В вариантной части

  • Тег
  • является необязательным и может быть любым допустимым идентификатором. Если вы опустите тег, опустите двоеточие (:) после него также.
  • ordinalType обозначает порядковый тип.
  • Каждый константаList является константой, обозначающей значение типа ordinalType или список таких констант с разделителями-запятыми. Нет значения быть представленными более одного раза в комбинированных константных списках.
  • Каждый вариант представляет собой список объявлений с разделителями с запятой, сходный с конструкциями fieldList: type в основной части тип записи. То есть вариант имеет вид:

    fieldList1: type1;  ... fieldListn: typen;

где каждый полевой список является допустимым идентификатором или списком с разделителями-запятыми идентификаторы, каждый тип обозначает тип, а конечная точка с запятой необязательный. Типы не должны быть длинными строками, динамическими массивами, вариантами (то есть типы Variant) или интерфейсы, и они не могут быть структурированы типы, содержащие длинные строки, динамические массивы, варианты или интерфейсы; но они могут быть указателями на эти типы.

Записи с вариантными частями сложны синтаксически, но обманчиво прост семантически. Вариантная часть записи содержит несколько вариантов, которые разделяют одно и то же пространство в памяти. Вы можете читать или пишите в любое поле любого варианта в любое время; но если вы напишете поле в одном варианте, а затем в поле в другом варианте, вы можете переписывать свои собственные данные. Тег, если он есть, действует как дополнительное поле (типа ordinalType) в невариантной части запись.


Как и для остальных, это довольно обычная процедура: LONGLONG - это 64-битное целое число, а UCHAR - unsigned 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, не имеет отдельных типов для Byte и AnsiChar. Но эти массивы выглядят так, как если бы они читались как текст, поэтому я предполагаю, что AnsiChar будет более подходящим.

Ответ 2

Аналогичную структуру можно найти в 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 just
    //  some metadata for the user 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;