Структуры

При интеграции MQL-программ с внешними системами, в частности, при отправке или получении данных через Интернет, возникает необходимость преобразовать структуры данных в массивы байтов. Для этих целей MQL5 API предоставляет две функции: StructToCharArray и CharArrayToStruct.

В обоих случаях предполагается, что структура содержит только простые встроенные типы, то есть все встроенные типы кроме строк и динамических массивов. Также структура может содержать другие простые структуры. Объекты классов и указатели запрещены. Подобные структуры называются еще POD (Plain Old Data).

bool StructToCharArray(const void &object, uchar &array[], uint pos = 0)

Функция StructToCharArray копирует POD-структуру object в массив array типа uchar. Опционально можно с помощью параметра pos указать позицию в массиве, начиная с которой будут помещаться байты. По умолчанию копирование идет в начало массива, причем динамический массив будет автоматически увеличен в размере, если его текущего размера недостаточно для всей структуры.

Функция возвращает признак успеха (true) или ошибки (false).

Проверим её работу с помощью скрипта ConversionStruct.mq5. Создадим новый тип структуры DateTimeMsc, которая включает стандартную структуру MqlDateTime (поле mdt) и дополнительное поле msc типа int для хранения миллисекунд.

struct DateTimeMsc
{
   MqlDateTime mdt;
   int msc;
   DateTimeMsc(MqlDateTime &initint m = 0) : msc(m)
   {
      mdt = init;
   }
};

В функции OnStart преобразуем некое тестовое значение datetime в нашу структуру и затем — в байтовый массив.

MqlDateTime TimeToStructInplace(datetime dt)
{
   static MqlDateTime m;
   if(!TimeToStruct(dtm))
   {
      // можно вывести код ошибки _LastError,
      // но здесь просто возвращаем нулевое время
      static MqlDateTime z = {};
      return z;
   }
   return m;
}
 
#define MDT(TTimeToStructInplace(T)
 
void OnStart()
{
   DateTimeMsc test(MDT(D'2021.01.01 10:10:15'), 123);
   uchar a[];
   Print(StructToCharArray(testa));
   Print(ArraySize(a));
   ArrayPrint(a);
}

Получим в журнале следующий результат (массив переформатирован с дополнительными переносами строк, чтобы подчеркнуть соответствие байтов каждому из полей):

   true
   36
   229   7   0   0
     1   0   0   0
     1   0   0   0
    10   0   0   0
    10   0   0   0
    15   0   0   0
     5   0   0   0
     0   0   0   0
   123   0   0   0

 

bool CharArrayToStruct(void &object, const uchar &array[], uint pos = 0)

Функция CharArrayToStruct копирует массив array типа uchar в POD-структуру object. С помощью параметра pos можно указать позицию в массиве, начиная с которой начнется чтение байтов.

Функция возвращает признак успеха (true) или ошибки (false).

Продолжая тот же пример (ConversionStruct.mq5), мы можем восстановить исходную дату и время из байтового массива.

void OnStart()
{
   ...
   DateTimeMsc receiver;
   Print(CharArrayToStruct(receivera));                 // true
   Print(StructToTime(receiver.mdt), "'"receiver.msc);  // 2021.01.01 10:10:15'123
}