Обсуждение статьи "Как за 10 минут написать DLL библиотеку на MQL5 (Часть II): Пишем в среде Visual Studio 2017"
может кому будет полезно, последнее время делаю именно так:
можно (и даже проще) использовать CodeLight IDE. По сравнению со студией она быстрая и менее "жручая", цепляет разные компиляторы, и микрософтовский в том числе.
до странного, но DLL используя gcc строится проще. В настройках проекта DLL указать нужный тулчайн (gcc32 бит для MT4, gcc64 для MT5). И собственно всё. Опционально добавить команду "скопировать DLL в иерархию MT" в PostBuild
Никакие свистопляски с *.def ненужны, при необходимости def генерится автоматом. Кстати, и DllMain вообще ненужен, его можно смело выкидывать :-) Точнее иногда бывает нужен, но крайне редко и это за гранью потребностей библиотек для MT.
Ещё момент - не освещённый в статье, но востребованный.
Если уж C++, то пожалуй должны быть классы и причём с обеих сторон, и в Mql и в С++.
"протаскивание класса C++ в Mql".
1. пишем (или берём готовый) класс :-)
получаем нечто такое :
#ifndef MQLPLUG_H #define MQLPLUG_H 1 #include "mql45.h" /** пример класса который "протаскивается" в MT **/ class Plug { public: Plug(); ~Plug(); mql_int OnInit(); void OnDeinit(mql_int); mql_int Sum(mql_int,mql_int); mql_double Median(MqlRates *rate); }; /* так как методы C++ нельзя "протащить" через DLL, а только функции C то и делаются простые функции делегирующие вызов к объекту */ MQL_API(Plug *) Plug_New(); MQL_API(void) Plug_Delete(Plug *); MQL_API(mql_int) Plug_OnInit(Plug *); MQL_API(void) Plug_OnDeinit(Plug *,mql_int); MQL_API(mql_int) Plug_Sum(Plug *,mql_int,mql_int); MQL_API(mql_double) Plug_Median(Plug *,MqlRates *rate); #endif
2. Реализация "функций-делегатов" тривиальна - первый агрумент это указатель на объект, внутри функции надо проверить его корректность, вызвать метод и перехватить исключения.
/// MqlPlug.cpp #include "MqlPlug.h" /*** функции-обёртки методов класса Plug все (кроме _New) первым аргументом получают указатель на объёкт прочие аргументы - такие же как у метода если переданные указатель корректен (не nullptr) то вызывается метод и заодно вылавливаются все исключения ***/ /// конструктор MQL_API(Plug *) Plug_New() { try { return new Plug; } catch (...) { } return nullptr; } /// деструктор MQL_API(void) Plug_Delete(Plug *plug) { try { delete plug; } catch (...) { } } // прочие методы MQL_API(mql_int) Plug_Sum(Plug *plug,mql_int one,mql_int two) { try { if (plug) return plug->Sum(one,two); } catch (...) { } return 0; } // и так далее
3. И наконец-то Mql ! В директивах импорт описываются функции-делегаты, и пишется класс имеющий единственное поле obj - хандлер (указатль на) объект, и методы вызывающите делегалов
#ifdef __MQL4__ // для 4-ки дескриптор (указатель) 32 бита) #define HANDLE int #else // для 5-ки - 64 #define HANDLE long #endif #import "Mql4Plug.dll" HANDLE Plug_New(void); void Plug_Delete(HANDLE); int Plug_OnInit(HANDLE); void Plug_OnDeinit(HANDLE,const int reason); int Plug_Sum(HANDLE,int,int); double Plug_Median(HANDLE,MqlRates &); #import class Plug { public: HANDLE obj; Plug() { obj = Plug_New(); } ~Plug() { Plug_Delete(obj); } int OnInit() { if (obj != NULL) { return Plug_OnInit(obj); } return INIT_FAILED; } void OnDeinit(const int reason) { if (obj != NULL) { Plug_OnDeinit(obj,reason); } } int Sum(int one,int two) { if (obj != NULL) { return Plug_Sum(obj,one,two); } return 0; } double Median(MqlRates &rates) { if (obj!=NULL) { return Plug_Median(obj,rates); } return EMPTY_VALUE; } };
PS/ Как-то раз такое запрашивали и я честно пытался объяснить. Но то-ли педагог из меня так-себе, то-ли визави в программировании был не аллё :-) Но популярные примеры осталась - поэтому делюсь
Добрый вечер. Сразу постараюсь на все ответить.
...
Никакие свистопляски с *.def ненужны, при необходимости def генерится автоматом. Кстати, и DllMain вообще ненужен, его можно смело выкидывать :-) Точнее иногда бывает нужен, но крайне редко и это за гранью потребностей библиотек для MT.
В статье говорится совершенно не о том, как генерить файл определений, можно, или нет это сделать, какой инструмент для этого использовать. В статье говорится для чего он нужен, для чего может быть применен в VS и что из этого получится. А как его сделать, чем и когда, это не важно.
Насчет DllMain. Теоретически Вы правы. Да, без этой функции можно обойтись. Я знаю инструменты, где DllMain не будет вызываться, даже, если она есть. А вот с категоричностью Вашего вывода, что это "за гранью" я совершенно не согласен. Я убежден, что такой вывод должен сделать сам разработчик, как несущий ответственность за результат. Если ему нужно, он может что то вызвать в DllMain. Не захочет - напишет отдельную экспортируемую функцию. Лично я не чувствую себя достаточно компетентным, что бы вот так запросто взять и лишить его дополнительной возможности.
Ещё момент - не освещённый в статье, но востребованный.
Если уж C++, то пожалуй должны быть классы и причём с обеих сторон, и в Mql и в С++.
"протаскивание класса C++ в Mql".
Вот совершенно не обязательно, что бы был экспорт классов. )) Спасибо, что Вы упомянули про эту возможность и отдельное спасибо за пример. Лично мне не приходило в голову делать что то подобное и тем более, рекомендовать такую методику начинающим разработчикам. Ну вот посмотрите сами на искусственность приведенного кода, на его не рациональность. И какая необходимость может заставить разработчика обращаться с указателями таким странным образом. Другими словами, если такой код не будет падать, то как теоретический пример он интересен, а с практической точки зрения - вряд ли) Больше скажу, по моему мнению, если у разработчика возникает необходимость в подобном экспорте, то, скорее всего, он очень сильно ошибся с дизайном Помимо этого, обращаю Ваше внимание на то, что где то половина статьи посвящена структурам, а это "почти классы". Стоит остановиться на этом и не идти по стопам некоторых наших коллег с форума, которые с удовольствием засунули бы в MQL весь С++17 ))
я с вами и не спорю ;-)
так - некоторые заметки которые вспомнились, глядишь кому и пригодится.
не споря со статьёй
какие такие "начинающие программисты" на стыке двух языков ?
PS/ кстати у вас там память упахана :-)
я с вами и не спорю ;-)
так - некоторые заметки которые вспомнились, глядишь кому и пригодится.
Спасибо, пригодится
но к сожалению вот такие хорошие примеры очень часто лежат в топиках форума, найти очень сложно, увы и сам этим грешу ))))
Если не лень, то в блог бы себе такие отличные примеры складывали бы, хоть какая вероятность, что найдется быстрее, но тоже не факт (((( -возможности у MQL потрясающие, но иногда быстрее самостоятельно прогуглить и найти готовый пример... да кстати, это форум очень хорошо индексируется гуглом, почти все запросы на тему нейросетей - будут результаты статей MQL ;)
я с вами и не спорю ;-)
так - некоторые заметки которые вспомнились, глядишь кому и пригодится.
не споря со статьёй
какие такие "начинающие программисты" на стыке двух языков ?
PS/ кстати у вас там память упахана
Что там с памятью, я наколбасил где то ?
Начинающий программист это понятие растяжимое ) Вот я совершенно точно начинающий программист в Питоне ) Или в ява скрипте. И много в чем еще я могу назвать себя начинающим. Вот и здесь, ну мало ли какая ситуация, если человек не делал раньше библиотек, а занимался двадцать лет САПРом, или плагины писал к Адобовским прогам? Конечно, он начинающий в новой области, но опытный в своей старой. В прочем ладно, не так уж и важна здесь эта терминология.
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
Опубликована статья Как за 10 минут написать DLL библиотеку на MQL5 (Часть II): Пишем в среде Visual Studio 2017:
Первоначальная "базовая" статья отнюдь не потеряла актуальности и всем интересующимся данной темой просто необходимо ее прочесть. Но с тех пор прошло достаточно много времени, сейчас актуальна Visual Studio 2017, в которой изменился, пусть ине значительно, интерфейс, да и сама платформа MetaTrader 5 развивалась и не стояла на месте. В статье рассмотрены этапы создания проекта dll, его настройки и совместной работы с инструментами терминала MetaTrader 5.
Создание простой DLL
Этот путь уже полностью проделан в первоначальной статье, здесь же мы повторим его, учитывая накопившиеся изменения.
Итак, в среде Visual Studio 2017 выбираем File -> New -> Project. В появившемся окне, в левой части, раскрываем список Visual C++ и в нем выбираем Windows Desktop, а в средней части выделяем строку Windows Desktop Wizard. В нижней части имеются несколько полей ввода, где можно изменить имя (рекомендуется задать свое и осмысленное) и месторасположение проекта (лучше оставить так, как предлагается). Всё готово, нажимаем кнопку "ОК" и переходим в следующее окно:
Здесь в выпадающем списке нужно выбрать Dynamic Link Library (.dll) и отметить галкой пункт "Export Symbols". На самом деле отмечать галкой этот пункт необязательно, но желательно начинающим разработчикам. В этом случае в файлы проекта будет добавлен демонстрационный код, который можно просмотреть, а затем удалить, либо закомментировать. Нажимаем на кнопку "ОК" и создаются файлы проекта, которые мы можем затем редактировать. Однако делать это еще рано, пока разберемся с настройками проекта. Во первых, нужно помнить, что MetaTrader 5 работает только с 64-х разрядными библиотеками. Если попытаться присоединить 32-х разрядную, то мы получим следующие сообщения:
'E:\...\MQL5\Libraries\Project2.dll' is not 64-bit version
Cannot load 'E:\MetaTrader 5\MQL5\Libraries\Project2.dll' [193]
Соответственно, никакой работы сделать будет нельзя.
Автор: Andrei Novichkov