Перейти к содержанию
Форекс Форум трейдеров Академии «MasterForex-V»

Взаимодействие с МТ4 через DLL


Рекомендуемые сообщения

В этой теме будет освещаться взаимодействие с терминалом МТ 4 посредством библиотек dll и Delphi.

Для МТ4 отсутствует API, потому работа с терминалом может осуществляться только через dll.

 

Для нормальной компиляции библиотеки потребуются компоненты из раздела Репозитарий классов

Ссылка на комментарий
Поделиться на другие сайты

  • 9 месяцев спустя...

Краткое отсутупление.

 

DLL (англ. Dynamic-link library — библиотека динамической компоновки) — понятие операционных систем Microsoft Windows и IBM OS/2; динамическая библиотека, позволяющая многократное применение различными программными приложениями. K DLL относятся также элементы управления ActiveX и драйверы.

 

Цели введения DLL

 

Первоначально предполагалось, что введение DLL позволит эффективно организовать память и дисковое пространство, используя только один экземпляр библиотечного модуля для различных приложений. Это было особенно важно для ранних версий Microsoft Windows с жёсткими ограничениями по памяти.

 

Далее, предполагалось улучшить эффективность разработок и использования системных средств за счёт модульности. Замена DLL-программ с одной версии на другую должна была позволить независимо наращивать систему, не затрагивая приложений. Кроме того, библиотеки DLL могли использоваться разнотипными приложениями — например, Microsoft Office, Microsoft Visual Studio и т. п.

 

В дальнейшем идея модульности выросла в концепцию COM.

 

Фактически, полных преимуществ от внедрения DLL получить не удалось по причине явления, называемого DLL hell («ад DLL»). DLL Hell возникает, когда несколько приложений требуют одновременно различные, не полностью совместимые, версии DLL-библиотек, что приводит к сбоям в этих приложениях. Когда система выросла до определённых размеров, количество DLL стало превышать многие тысячи, не все из них обладали полной надёжностью и совместимостью, и конфликты типа DLL Hell стали возникать очень часто, резко понижая общую надёжность системы. Поздние версии Microsoft Windows стали разрешать параллельное использование разных версий DLL, что свело на нет преимущества изначального принципа модульности.

 

Информация взята с сайта http://ru.wikipedia.org/wiki/DLL

Ссылка на комментарий
Поделиться на другие сайты

Пример простейшей DLL.

 

library Example;

{ Производим некие действия и возвращаем результат }
function AddNumbers(a, b: Double): Double; cdecl;
begin
  AddNumbers := a + b
end;

{ Эта функция экспортируется }
exports
 AddNumbers;

{ Инициализатор DLL, аналог функции main() в языках C и C++ }
begin
end.

 

Информация взята с сайта http://ru.wikipedia.org/wiki/DLL

 

Разберем указанный пример:

 

library Example;

 

library - зарезервированне слово в начале модуля, обозначает что данный исполняемый файл будет являться библиотекой.

Example - имя создаваемой библиотеки.

 

далее следует объявление функции AddNumbers, которая выполняет сложение двух чисел с плавающей запятой.

 

exports AddNumbers;

exports - зарезервированное слово, обозначает, что функция AddNumbers будет объявлена как экспортная и ее можно будет использовать другими приложениями.

 

Ниже расположены

 

begin
end.

 

основного модуля библиотеки. В момент ее инициализации будут выполнены директивы находящиеся в теле основного модуля.

Ссылка на комментарий
Поделиться на другие сайты

Вызов функции из библиотеки.

 

Пример 1:

 

program Example;
{$APPTYPE CONSOLE}

{ Указываем, что функция находится в DLL }
function AddNumbers(a, b: Double): Double; cdecl; external 'Example.dll';

{ Используем функцию как обычно }
var result: Double;
begin
 result := AddNumbers(1, 2);
 Writeln('The result was: ', result)
end.

 

Пример 2:

 

program Example;
{$APPTYPE CONSOLE}

uses Windows; // строчка добавлена мною для нормальной компиляции библиотеки под Windows

var result: Double;
   LibHandle: Hmodule;
   AddNumbers: function(a, b: Double): Double;
begin
  LibHandle := LoadLibrary('Example.dll'); // загружаем DLL
  if LibHandle <> 0 then
    begin
      @AddNumbers := GetProcAddress(LibHandle, 'AddNumbers'); // запоминаем адрес
                                                              // необходимой функции
      if @AddNumbers <> nil then
        begin
          result := AddNumbers(1, 2);       // используем функцию
          Writeln('The result was: ', result);
        end;
      FreeLibrary(LibHandle);               // выгружаем DLL
    end;
end.

 

Текст модулей взят с сайта http://ru.wikipedia.org/wiki/DLL

 

Оба примера демонстрируют нам вызов функции из ранее скопилированной библиотеки Example.dll из программы с той лишь разницей, что второй пример проверяет, что библиотека инициализирована и загружена в память. Первый и второй варианты демонстрируют нам вывод на экран результат сложения чисел a и b.

 

Исходные файлы примеров можно скачать из данного поста по ссылке ниже.

Перед запуском приложений не забудьте переписать Example.dll в каталог исполняемого файла.

Простейшая библиотека и ее вызов.rar

Ссылка на комментарий
Поделиться на другие сайты

Необходимость использования DLL в платформе Metatrader

 

В первую очередь необходимо ответить на самый главный вопрос "Для чего?" или "Зачем?".

 

Задачи, которые будут решать библиотеки, как правило дополняют возможности торговой платформы MT4 и MT5, так как с плюсами у вышеперечисленных платформ есть и два существенных минуса:

1. Язык платформ не "всесилен". Это, я бы сказал, один из самых главных минусов. Метаязык MQL умеет многое, но имного чего не имеет (меня, например, не устраивают возможности MQL с точки зрения формирования отчетов, я могу захотеть, например чтобы мне MT отправлял SMS-ки с какой-нибудь информацией :biggrin:, хочу чтобы данные обрабатывались внешним SQL, скажем FireBird'ом и т.д.)

2. MQL при всех своих плюсах имеет очень ярко выраженный минус - он очень "прожорлив", т.е. съедает большое количество оперативной памяти компьютера (но это не так страшно при наших-то текущих возможностях: сходил в магазин, докупил модуль памяти и порядок :smile:) и очень (я бы даже сказал - ОЧЕНЬ) медленно работает: это хорошо видно тогда, когда у Вас используется большое количество самописных индикаторов. Поскольку платформа Metatrader постоянно обновляет экран (это происходит при получении каждой новой котировки, т.е. выполняется функция start() и происходит дикая нагрузка на ядро - экран-то надо перерисовать... И у MT нет другого выхода он каждый новый тик перерисовывает экран, постоянно получает из базы и пересчитывает нужные данные :sad:.

Что делать - за все приходится платить - простота программирования на MQL имеет и обрабную сторону медали.

 

Но опять же развивая тему - MQL очень облегчает нам жизнь в плане визуализации информации, т.е. графической части, модуля связи с дилерами, экранных форм, готовых индикаторов и пр., имеет кучу готовых классов для работы с данными.

Но хочется, как говорится, всегда большего - хочется такое же но ... как в известном фильме "с перламутровыми пуговицами". Поэтому предлагаю компромиссный вариант - оставить все "вкусности" MQL по визуальной части, а то что он делает (т.е. MQL) медленно - так это математическую обработку информации и выборку данных.

Вот пусть этим и будут заниматься нами разрабатываемые библиотеки.

Ссылка на комментарий
Поделиться на другие сайты

О правилах написания DLL для MT

 

Ниже будут приведены примеры по написанию DLL для МТ.

Краткое отступление: данный пост написан для людей не сильно разбирающихся в тонкостях программирования, знаний архитектуры компьютера и работы с памятью, по этому люди хорошо владеющие Delphi могут то что написано ниже не читать.

 

Там где начинаются внешние вызовы библиотек - в действие вступает обработчик ядра - великий и могучий Windows. Основная проблема заключается как раз в том, что способы хранения данных в разных операционных системах отличаются (Borland Delphi разрабатывали для разных операционных систем), таким образом необходимо "подружить" ядро и Delphi. Начинающие программисты часто наступают на такие "грабли" - программы у них или выдают ошибки, или выдают "не те" данные либо "вешают" приложения :biggrin: . Этот пост написан как раз для того, чтобы такие ошибки по возможности исключить.

 

Перед тем как приступить к описательной части необходимо сразу же озвучить несколько правил:

1. Первое и самое основное: библиотеки, которые мы будем создавать, оперируют своими собственными типами, которые может "не понять" Windows, поэтому необходимо все экспортируемым процедурам и функциям присваивать стандартный вызов - директиву stdcall. Без использования стандартного вызова обработчик ядра может вызвать исключение и остановить выполнение приложения, которое загрузило данную библиотеку (в нашем случае - этим приложением будет MT).

2. Следствие из п.1 - если мы используем стандартный вызов, то должны передавать в MT все данные с которыми "умеет" работать ядро. Ну и ничего страшного, нам в полне хватит и тех, которые знает Windows :smile:.

3. Следует так же уделить внимание передаче строковых переменных между MT4 и DLL. Надо помнить о том, что строковые данные могут храниться в различных кодировках. Ну этому будет посвящена отдельная статья.

 

На этом краткое отступление закончено, если у кого есть желание изучить данную тему подробнее - рекомендую любую книжку по программированию Delphi или почитать ветку форума по начальной теории.

Ссылка на комментарий
Поделиться на другие сайты

как в одном известном анекдоте "Ну а теперь слайды" :smile:.

 

Сразу хочется отметить, что примеров в Интеренте находится куча, так что мы тоже не будем изобретать велосипед - возьмем самый простой пример его разберем. Вот текст моделя создаваемой нами библиотеки:

 

library MT_DLL;

function _Sum(_a: integer; _b: integer): integer; stdcall;
begin
 Result := _a + _b;
end;

exports
  _Sum name 'CustomSum';

begin
end.

 

Как видите, не такой уж это и страшный "зверь".Только два момента хочу отметить:

1. Вызов функции _Sum идет с указанием директивы stdcall (этому вопросу посвящен предыдущий пост)

2. Директивой exports функции переприсвоено имя, таким образом, из MT будет выполняться вызов функции по имени CustomSum а не _Sum

 

а теперь сам текст скрипта на MQL:

 

 

// директива импорта данных из библиотеки. 
// Библиотека должна находиться в каталоге "<Каталог установки МТ>\experts\libraries\"
#import "MT_DLL.dll"
// объявление функции, которая находится в библиотеке.
int CustomSum(int a, int b);
#import

#property indicator_chart_window

int init()
{
int _temp = 5;
 	string Msg;

 	// а вот и вызов нашей функции.
 	int sum1 = CustomSum( 1, _temp); 
 	
//---- индикация суммы
 	Print( "Sum is: ", sum1);

  	return(0);
}

 

Теперь добавьте индикатор на график.

Если вы сделали все правильно после инициализации нашего индикатора на закладке "Эксперты" будет следующая запись:

Sum is: 6

 

Можете себя поздравить - у нас получилось импортировать вызов функции из библиотеки в MT.

 

исходные тексты можно скачать отсюда

DllMT.rar

Ссылка на комментарий
Поделиться на другие сайты

Гость
Эта тема закрыта для публикации ответов.
×
×
  • Создать...