Скачать MetaTrader 5

Краш терминала при чтении данных (dll)

Авторизуйтесь или зарегистрируйтесь, чтобы добавить комментарий
Торгуй с помощью MetaTarder 5. Скачай прямо сейчас!
a1exb
29
a1exb 2016.08.05 18:07 

Приветствую.

Появилась потребность  в обмене даннымим между индикаторами. Гугл привел к

https://www.mql5.com/ru/articles/19

Регистрация данных в глоб. переменных проходит норм.

А вот при попытке чтения с помощью GetIndicatorValue - краш.

Я перекомпили под х64 в студии, ошибок нет. Только ворнинги по типу

1>IndEx.cpp(4): warning C4311: приведение типов: усечение указателя из "double *" в "int"
1>IndEx.cpp(4): warning C4302: приведение типов: усечение из "double *" в "int"
1>IndEx.cpp(9): warning C4312: приведение типов: преобразование из "int" в "double *" большего размера
1>IndEx.cpp(14): warning C4312: приведение типов: преобразование из "int" в "double *" большего размера

 Подскажите пожалуйста что я делаю не так? 

 Думал, что индекс элемента выходит за пределы (хотя это по идее быть не должно, т..к выход проверяется в самой GetIndicatorValue ), читал всегда 0 элемент - все равно краш.

Может есть какие-то отличия в чтении между х86 и х64? 

--- 

MT5 5.0 build 1375

Visual studio 2015

win 10 x64 

Ihor Herasko
9061
Ihor Herasko 2016.08.05 18:54  
a1exb:

Только ворнинги по типу

 Подскажите пожалуйста что я делаю не так?  

Опять же - нужен код (MQL5 и С++). Также нужно заметить, что ворнинги вовсе не безобидные: там речь о приведении указателей на double к числу int. Это достаточно серьезно.
a1exb
29
a1exb 2016.08.06 03:53  
Ihor Herasko:
Опять же - нужен код (MQL5 и С++). Также нужно заметить, что ворнинги вовсе не безобидные: там речь о приведении указателей на double к числу int. Это достаточно серьезно.
Я сейчас с телефона и кода под рукой нет.  Но он есть в статье, которую я указал в начале. Я его не менял, компилировал пустой dll проект в студии под х64. 
a1exb
29
a1exb 2016.08.07 09:30  
Ihor Herasko:
Опять же - нужен код (MQL5 и С++). Также нужно заметить, что ворнинги вовсе не безобидные: там речь о приведении указателей на double к числу int. Это достаточно серьезно.

DLL:

extern "C" __declspec(dllexport) int __stdcall GetPtr(double *a)
{
        return((int)a);
}

extern "C" __declspec(dllexport) double __stdcall GetValue(int pointer,int i)
{
        return(((double*) pointer)[i]);
}

extern "C" __declspec(dllexport) void __stdcall SetValue(int pointer,int i,double value)
{
        ((double*) pointer)[i]=value;

 Работа с длл:

#import "IndEx.dll"
int GetPtr(double &a[]);
double GetValue(int pointer,int i);
void SetValue(int pointer,int i,double value);
#import
//+------------------------------------------------------------------+
//| зарегистрировать буфер                                           |
//+------------------------------------------------------------------+
void RegisterBuffer(double &Buffer[],string name,int mode) export
  {
   UnregisterBuffer(Buffer);                    //сначала удалим на всякий случай переменную

   int direction=0;
   if(ArrayGetAsSeries(Buffer)) direction=1;    //устанавливаем флаг направления индексации

   name=name+"#"+IntegerToString(mode)+"#"+Symbol()+"#"+IntegerToString(Period())+
        "#"+IntegerToString(ArraySize(Buffer))+"#"+IntegerToString(direction);
   int ptr=GetPtr(Buffer);                //вытаскиваем указатель
   if(ptr==0) return;

   MathSrand(ptr);                            //очень удобно использовать значение указателя (а не время) для инициализации ГПСЧ

   while(true)
     {
      int rnd=MathRand();
      if(!GlobalVariableCheck(name+"#"+IntegerToString(rnd))) //обеспечим уникальность - полагаем, что вряд ли кому придет в голову 
        {                                         //исследовать больше, чем RAND_MAX буферов:)
         name=name+"#"+IntegerToString(rnd);
         GlobalVariableSet(name,ptr);         //ну и записываем в глобальные
         break;
        }
     }
  }
//+------------------------------------------------------------------+
//| снять регистрацию буфера                                         |
//+------------------------------------------------------------------+
void UnregisterBuffer(double &Buffer[]) export
  {
   int ptr=GetPtr(Buffer);                  //будем разрегистрироваться по фактическому адресу буфера
   if(ptr==0) return;

   int gt=GlobalVariablesTotal();
   int i;
   for(i=gt-1;i>=0;i--) //просто перебрать все глобальные переменные 
     {                                            //и удалить наш буфер отовсюду, где он "засветился"
      string name=GlobalVariableName(i);
      if(GlobalVariableGet(name)==ptr)
         GlobalVariableDel(name);
     }
  }
//+------------------------------------------------------------------+
//|  найти буфер                                                     |
//+------------------------------------------------------------------+
int FindBuffers(string name,int mode,string symbol,int period,string &buffers[]) export
  {
   int count=0;
   int i;
   bool found;
   string name_i;
   string descriptor[];
   int gt=GlobalVariablesTotal();

   StringTrimLeft(name);                                    //обрезать строку от лишних пробелов
   StringTrimRight(name);

   ArrayResize(buffers,count);                              //обнулить размер

   for(i=gt-1;i>=0;i--)
     {
      found=true;
      name_i=GlobalVariableName(i);

      StringExplode(name_i,"#",descriptor);                 //разбить строку на поля
      if(ArraySize(descriptor)<4) continue;
      if(StringFind(descriptor[0],name)<0 && name!=NULL) found=false;      //проверяем каждое поле на соответствие критерию поиска
      if(((int)descriptor[1]!=mode) && (mode>=0)) found=false;
      if((descriptor[2]!=symbol) && (symbol!=NULL)) found=false;
      if(((int)descriptor[3]!=period) && (period>0)) found=false;

      if(found)
        {
         count++;                                           //все условия сошлись, заносим в список
         ArrayResize(buffers,count);
         buffers[count-1]=name_i;
        }
     }

   return(count);
  }
//+------------------------------------------------------------------+
//| получить значение индикатора по дескриптору и индексу            |
//+------------------------------------------------------------------+
double GetIndicatorValue(string descriptor,int shift) export
  {
   int ptr;
   string fields[];
   int size,direction;
   if(GlobalVariableCheck(descriptor)>0) //убедились в валидности дескриптора
     {
      ptr=(int)GlobalVariableGet(descriptor);                  //получили значение указателя
      if(ptr!=0)
        {
         StringExplode(descriptor,"#",fields);              //разбили имя дескриптора на поля
         if(ArraySize(fields)<4) return EMPTY_VALUE;
         size=(int)(fields[4]);                                  //нам нужен текущий размер массива
         direction=(int)(fields[5]);
         if(direction==1) shift=size-1-shift;               //если индексация с конца
         if(shift>=0&&shift<size)                           //проверка правильности индекса - чтобы не уронить терминал
            return(GetValue(MathAbs(ptr),shift));           //добро, возвращаем значение
        }
     }
   return(EMPTY_VALUE);                                     //в противном случае извиняйте...
  }
//+------------------------------------------------------------------+
//| установить значение для индикатора по индексу                    |
//+------------------------------------------------------------------+
bool SetIndicatorValue(string descriptor,int shift,double value) export
  {
   int ptr;
   string fields[];
   int size,direction;
   if(GlobalVariableCheck(descriptor)>0) //убедились в валидности дескриптора
     {
      ptr=(int)GlobalVariableGet(descriptor);                  //получили значение указателя
      if(ptr!=0)
        {
         StringExplode(descriptor,"#",fields);              //разбили имя дескриптора на поля
         if(ArraySize(fields)<4) return false;
         size=(int)(fields[4]);                                  //нам нужен текущий размер массива
         direction=(int)(fields[5]);
         if(direction==1) shift=size-1-shift;               //если индексация с конца
         if(shift>=0&&shift<size)                           //проверка правильности индекса - чтобы не уронить терминал
           {
            SetValue(MathAbs(ptr),shift,value);
            return(true);
           }
        }
     }
   return(false);
  }
//+------------------------------------------------------------------+
//| разделить строку на подстроки в массив                           |
//+------------------------------------------------------------------+
void StringExplode(string s,string separator,string &result[])
  {
   int i,pos;
   ArrayResize(result,1);

   pos=StringFind(s,separator);
   if(pos<0) {result[0]=s;return;}

   for(i=0;;i++)
     {
      pos=StringFind(s,separator);
      if(pos>=0)
        {
         result[i]=StringSubstr(s,0,pos);
         s=StringSubstr(s,pos+StringLen(separator));
        }
      else break;
      ArrayResize(result,ArraySize(result)+1);
     }
  }
//+------------------------------------------------------------------+

 Вызов из-за которого крашится:

...
   found=FindBuffers("AC_DN_Signal",0,_Symbol,_Period,import_bufs);
   if(found>0) import_ACDNbuf=import_bufs[0];
   else import_ACDNbuf=NULL;
...
   if(import_ACDNbuf!=NULL)
   {
   double tmp_sig=GetIndicatorValue(import_ACDNbuf,0);
   ...
   }
Комбинатор
15930
Комбинатор 2016.08.07 11:38  
Для x64 в дллке все int надо заменить на long
a1exb
29
a1exb 2016.08.07 11:59  
Комбинатор:
Для x64 в дллке все int надо заменить на long

Не помогло =(

Я может как-то не так сделал? Исправил все инт на лонг, перекомпили под х64, скопировал свежую длл в папку МТ, но при импорте все равно отображается как инт. ДЛЛ точно свежая, а не старая.


UPD: этот вопрос решил, поменяв инт на лонг в exchng.mq5 в описании импорта функций длл (это самый длинный исходник в начале темы)

Авторизуйтесь или зарегистрируйтесь, чтобы добавить комментарий