Вызов импортируемых функций

Для импорта функций во время выполнения mql5-программы используется раннее связывание. Это значит, что если в программе есть вызов импортируемой функции, то соответствующий модуль (ex5 или dll) загружается в процессе загрузки программы. Библиотеки MQL5 и DLL выполняются в потоке вызывающего модуля.

Не рекомендуется использовать полностью квалифицированное имя загружаемого модуля вида Drive:\Directory\FileName.Ext. Библиотеки MQL5 загружаются из папки terminal_dir\MQL5\Libraries. Если библиотека не была найдена, то производится попытка загрузить библиотеку из папки terminal_dir\experts.

Системные библиотеки (DLL) загружаются по правилам операционной системы. Если библиотека уже загружена (например, другим экспертом и даже из другого клиентского терминала, запущенного параллельно), то обращение идет к уже загруженной библиотеке. В противном случае поиск идет в следующей последовательности:

  1. Директория из которой был запущен модуль, импортирующий dll. Под модулем понимается эксперт, скрипт, индикатор или библиотека EX5;
  2. Директория каталог_данных_терминала\MQL5\Libraries (TERMINAL_DATA_PATH\MQL5\Libraries);
  3. Директория, из которой был запущен клиентский терминал MetaTrader 5;
  4. Системная директория;
  5. Директория Windows;
  6. Текущая директория;
  7. Директории, перечисленные в системной переменной PATH.

Если библиотека DLL использует в своей работе другую DLL, то в случае отсутствия второй DLL первая не сможет загрузиться.

Перед загрузкой эксперта (скрипта, индикатора) формируется общий список всех библиотечных модулей EX5, которые предполагается использовать как из загружаемого эксперта (скрипта, индикатора), так и из библиотек из этого списка. Таким образом обеспечивается однократная загрузка многократно используемых библиотечных модулей EX5. Библиотеки пользуются предопределенными переменными вызвавшего их  эксперта (скрипта, индикатора).

Поиск импортируемой библиотеки EX5 производится в следующей последовательности:

  1. Директория, путь к которой задается относительно директории импортирующего EX5 эксперта (скрипта, индикатора);
  2. Директория каталог_терминала\MQL5\Libraries;
  3. Директория MQL5\Libraries в общей директории всех клиентских терминалов MetaTrader 5 (Common\MQL5\Libraries).

Функции, импортируемые из DLL в mql5-программу, должны обеспечивать соглашение о связях, принятое для функций Windows API. Для обеспечения такого соглашения в исходном тексте программ, написанных на языках C или C++, используется ключевое слово __stdcall, которое является специфическим для компиляторов от фирмы Microsoft(r). Обсуждаемое соглашение о связях характеризуется следующим:

  • вызывающая функция (в нашем случае mq5-программа) должна "видеть" прототип вызываемой (импортируемой из DLL) функции, для того чтобы правильно сложить параметры на стек;
  • вызывающая функция (в нашем случае mql5-программа) складывает параметры на стек в обратном порядке, справа налево - именно в таком порядке импортируемая функция считывает переданные ей параметры;
  • параметры передаются по значению, за исключением тех, которые явно передаются по ссылке (в нашем случае строк);
  • импортируемая функция, считывая переданные ей параметры, сама очищает стек.

При описании прототипа импортируемой функции можно использовать параметры со значениями по умолчанию.

В случае если соответствующая библиотека не смогла загрузиться, либо установлен запрет на использование DLL, либо импортируемая функция не была найдена – эксперт останавливает свою работу с соответствующим сообщением "expert stopped" в журнале. При этом эксперт не будет запускаться, пока не будет заново проинициализирован. Эксперт может быть переинициализирован в результате перекомпиляции либо после открытия таблицы свойств эксперта и нажатия кнопки OK.

Передача параметров

Все параметры простых типов передаются по значению, если явно не указано, что они  передаются по ссылке. При передаче строки передается адрес буфера скопированной строки; если строка передается по ссылке, то в функцию, импортируемую из DLL, передается адрес буфера именно этой строки без копирования.

Структуры, содержащие динамические массивы, строки, классы, другие сложные структуры, а также статические либо динамические массивы перечисленных объектов, не могут быть переданы в качестве параметра в импортируемую функцию.

При передаче в DLL массива всегда (независимо от флага AS_SERIES) передается адрес начала буфера данных. Функция внутри DLL ничего не знает о флаге AS_SERIES, переданный массив является статическим массивом неизвестной длины, для указания размера массива используйте дополнительный параметр.