Переносим алгоритм советника в DLL

 

Столкнулся с проблемой - язык MQL4 не позволяет реализовать сложный алгоритм работы советника. Для этого нужно ООП. Оно есть в MQL5, но он пока мало распространен. Здесь на форуме советовали вынести весь код в DLL. Скачал с оф.сайта MS Visual Studio 2010 Express. Установил Visual C++ 2010. Создал проект, написал несколько функций, скомпилировал DLL и подключил ее к тестовому индикатору. И тут пошли проблемы...

Никак не удается отладить элементарный механизм обмена данными между индикатором и DLL.
Допустим, в DLL есть код:

extern "C" __declspec (dllexport) double GetValue(double val);
extern "C" __declspec (dllexport) double GetZero();

double GetValue(double val)
{
return val+0.0001;
}

double GetZero()
{
return 0.0;
}

В индикаторе импортируем DLL:

#import "my.dll"
double GetValue(double);
double GetZero();

При вызове GetZero() возвращается 0.0, как положено, но при вызове GetValue(1.1) терминал падает (закрывается и даже не пишет об ошибке в лог). Если использовать в DLL объявление такого вида (так видел во многих примерах):

extern "C" __declspec (dllexport) double __stdcall GetValue(double val);

то вызов функции не срабатывает, но терминал не падает.

Я уж не знаю, что думать... может я функции объявляю неверно, а может размерность double в VC++ и MQL4 отличается. Может кто подскажет, в чем тут дело?

Возможно, у кого то есть пример простейшей DLL для подключения в терминале? Меня интересует передача данных в DLL и из нее...
1. Вызов функции и передача ей параметра типа int, double, array[], string
2. Возврат функцией значения типа int, double, array[], string
3. Интересует возможность создания массива в памяти DLL (или иной памяти, управляемой) и передача указателя на этот массив так, чтобы его можно было бы читать из кода MQL
4. Методы отладки DLL, запущенного терминалом (как вариант ведение лога в текстовом файле)

Буду признателен за любую полезную информацию по теме. Заранее спасибо!




 
andreybs:

Столкнулся с проблемой

Как всегда, можно ответить, что весьма полезно бывает читать справку. Например:

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


Возможно, у кого то есть пример простейшей DLL для подключения в терминале? Меня интересует передача данных в DLL и из нее...
1. Вызов функции и передача ей параметра типа int, double, array[], string
2. Возврат функцией значения типа int, double, array[], string
3. Интересует возможность создания массива в памяти DLL (или иной памяти, управляемой) и передача указателя на этот массив так, чтобы его можно было бы читать из кода MQL
4. Методы отладки DLL, запущенного терминалом (как вариант ведение лога в текстовом файле)

Буду признателен за любую полезную информацию по теме. Заранее спасибо!


Во истину - лень раньше родилась ...... А Вы не пробовали смотреть пример, поставляемый с терминалом ;) ??? Это если уж совсем лень читать справку ;)....
 
alsu:

Как всегда, можно ответить, что весьма полезно бывает читать справку. Например:

Поскольку вторая функция в вашем коде не имеет параметров, то соглашение по сути и не нарушается, терминал не падает. А вот с первой, где есть передаваемый параметр, возникает вполне закономерный крэш, который так же закономерно устраняется указанием модификатора __stdcall.

Я же писал - когда вставляешь "__stdcall", то вообще все перестает работать, даже GetZero();
 
Берете тестовый проект из МТ- и проверяете как оно работает.
А оно работает.
Дальше- контрольное списывание.
Для непрограммистов почему-то нормально пропустить
важные ключевые слова в объявлении функции и важные настройки проекта.
 
alsu:
по поводу того, что вызов функции "не срабатывает" - как вы это определили?

Тестовый индикатор рисует на основном графике EURUSDH1 цены закрытия. Если линия есть, значит "срабатывает", иначе "не срабатывает". Так вот, заменяем цену закрытия на GetZero() и перекомпилируем индикатор - график рисует линию "в нуле", значения 0.0000. Но когда подключаем GetValue(iClose(...)) или GetValue(1) вместо GetZero() и перекомпилируем индикатор, то линия пропадает, а значения становятся "пустыми" (null). Далее никакие изменения в индикаторе не срабатывают, перекомпиляция индикатора не влияет, лечится только перезагрузкой терминала.
 
VladislavVG:
Во истину - лень раньше родилась ...... А Вы не пробовали смотреть пример, поставляемый с терминалом ;) ??? Это если уж совсем лень читать справку ;)....

jartmailru:
Берете тестовый проект из МТ- и проверяете как оно работает.
А оно работает.


Мы говорим о \experts\samples\DLLSample\ ?

Пробовал. Объявлял, как там.

__declspec (dllexport) double __stdcall GetValue(double val);
__declspec (dllexport) double __stdcall GetZero();

Не работает.

 
andreybs:
Пробовал. Объявлял, как там.

__declspec (dllexport) double __stdcall GetValue(double val);
__declspec (dllexport) double __stdcall GetZero();

Не работает.

Ну вот не надо
"Пробовал. Объявлял, как там.".
.
Компилите ТОТ проект как он есть- проверяете.
 
jartmailru:
Берете тестовый проект из МТ- и проверяете как оно работает.
А оно работает.
Дальше- контрольное списывание.
Для непрограммистов почему-то нормально пропустить
важные ключевые слова в объявлении функции и важные настройки проекта.

Тестовый проект написан в какой-то древней VC. VC2010 не открывает его. Аналогичные вызовы не срабатывают. Может нужно какие-то параметры компилятору задать в VC?
 
def- файл надо.
.
PS: а я бы скачал более старую студию.
Потому что если примеры не работают- то это странно...
Причина обращения: