Навигация:
<< >> Оглавление Указатель

Приложения

Приложение А. Функции, константы и структуры RDS

А.1. Типы параметров

А.1.2. Выравнивание полей служебных структур

Во многих случаях для передачи данных между пользовательской моделью блока или внешним модулем и главной программой RDS используются структуры данных. Иногда они заполняются в RDS и считываются в модуле пользователя (например, структура данных блока), иногда наоборот, заполняются в модели и считываются в RDS при вызове одной из сервисных функций. Эти структуры описаны в файле заголовков «RdsDef.h».

Поскольку разные модули могут быть созданы при помощи разных компиляторов, необходимо, чтобы поля скомпилированных структур имели одинаковые смещения в байтах от начала структуры и в RDS, и в пользовательском модуле – например, в модели блока. Это достигается принудительным выравниванием полей по границам шестидесятичетырехбитных (восьмибайтовых) слов в описаниях структур. Для этого каждое поле в каждой структуре описано как на анонимное объединение (union), состоящее из самого поля и дополнительного служебного поля размером в 8 байтов (для полей-массивов служебные поля тоже будут массивами).

Рассмотрим для примера условную структуру следующего вида:

  typedef struct
  { char cField;      // Односимвольное поле (1 байт)
    double dField;    // Вещественное поле (8 байтов)
    int iField;       // Целое поле (4 байта)
  } RDS_SOMESTRUCT;

Здесь поле cField имет нулевое смещение относительно начала струкутры. Смещения остальных полей определяются настройками компилятора. При плотной упаковке, например, поле dField будет иметь смещение 1 (перед ним – один байт), поле iField – смещение 9 (перед ним – один байт и восемь байтов). При других параметрах смещения dField и iField могут быть 8 и 16 байтов соответственно (выравнивание Quad Word). В главной программе RDS и моделях блоков параметры выравнивания должны быть одинаковыми, иначе кто-то из них будет обращаться «мимо» полей структуры, заполненной другим. Во многих случаях выравнивание данных можно указать в параметрах компилятора при его запуске, однако, RDS и DLL моделей блоков могут компилироваться разными компиляторами с разными возможностями и настройками. По этой причине описания структур RDS сделаны таким образом, чтобы одинаковое выравнивание обеспечивалось автоматически.

Если все поля структуры имеют одинаковый размер, с большой вероятностью они будут расположены друг за другом без зазоров. Поэтому приведенная выше структура в «RdsDef.h» во второй версии RDS имела бы следующий вид:

  typedef struct
  { union
      { char cField;      // Односимвольное поле (1 байт)
        double align0;    // Служебное поле для выравнивания
      };
    union
      { double dField;    // Вещественное поле (8 байтов)
        double align1;    // Служебное поле для выравнивания
      };
    union
      { int iField;       // Целое поле (4 байта)
        double align2;    // Служебное поле для выравнивания
      };
  } RDS_SOMESTRUCT;

Здесь анонимное объединение, в которое входит каждое поле исходной структуры, всегда занимает 8 байтов, независимо от размера самого поля. Таким образом, смещения полей cField, dField и iField будут равны 0, 8 и 16 соответственно, независимо от того, какой компилятор будет обрабатывать исходный текст модели. Поля align0, align1 и align2 – служебные, и обращаться к ним в программе не следует (это бессмысленно). Последнее из выравнивающих полей (align2), очевидно, не требуется, хотя и не мешает (оно добавлено при автоматическом формировании файла «RdsDef.h»).

Поле align1 тоже, в принципе, не требуется (dField и так имеет нужный размер), но, в отличие от этого примера, в настоящем «RdsDef.h» в качестве типа для выравнивания вместо double используется платформо-зависимая константа RDSBIGGESTTYPE. Для платформы Win32 в качестве этого «выравнивающего» типа используется double, для платформы Win64 – void*. Это самые большие по размеру типы, используемые в описаниях RDS.


<< >> Оглавление Указатель