ArrayCopyRates() - What's the mistake?

 

Hi everybody,

I'm trying to code a dll template with Microsoft Visual C++ 2010 Express to protect my EAs from unauthorized access.

Of course I need ArrayCopyRates() to get access to the rates ... but unfortunately it doesn't function.

I studied the samples and cannot find the mistake.

The error occurs when I call "GetRatesItemValue" (I named it "Kursdatenzeiger".).

When I print its results just senceless stuff is to be seen. In addition the results are also dynamic.

That means for example at first it gives "-181900000000xxxxxxxxxxxxxxxxxx" then a basically possible rate like "76.345" occurs which is also not correct. But most often its just "0".

I searched the web and recognized that there are also other people facing problems by applying "ArrayCopyRates()" but I did'nt find an answer yet.

(Because I'm German I changed the names oft the variables. I hope it doesn't disturb you.)


double Funktionen::Kursdatenzeiger(const KursInfo* kursdaten, const int baranzahl, const int shift, const int auswahl)
{
//----
if(kursdaten==NULL)
{
printf("FEHLER: Leerer Array!\n");
return(1);
}
//----
if(baranzahl<=0)
{
printf("Fehler: Falsche Baranzahl! (%d)\n", baranzahl);
return(2);
}
//----
if(shift<0 || shift>=baranzahl)
{
printf("Fehler: Falscher Shift (%d)\n", shift);
return(3);
}
//----
if(auswahl<0 || auswahl>5)
{
printf("Fehler: Falscher Kursartindex (%d)\n", auswahl);
return(4);
}
//----
int Zeiger=baranzahl-1-shift;
switch(auswahl)
{
case 0: return double(kursdaten[Zeiger].ctm);
case 1: return kursdaten[Zeiger].open;
case 2: return kursdaten[Zeiger].low;
case 3: return kursdaten[Zeiger].high;
case 4: return kursdaten[Zeiger].close;
case 5: return kursdaten[Zeiger].vol;
}
//----
return(5);
}

Hoping anybody of you can help!

 

Are you programming in MQL5?

 

No I'm not.

The code I wrote in my entry was the C++ code for the dll.

 
vostro1500:

double Funktionen::Kursdatenzeiger(const KursInfo* kursdaten, const int baranzahl, const int shift, const int auswahl)

I don't think that this can be the problem, because you'd get a different kind of error... but is this function definitely getting compiled as __stdcall rather than __cdecl ?
 

I just removed the __stdcall recently. It does not make any difference.


Maybe its helpful when I add the mql4 code:

int start()
  {
   double kurse[][6];
   int fehler;
   for (int neuversuche=3; neuversuche>0; neuversuche--)
      {      
         ArrayCopyRates(kurse,NULL,0);
         fehler = GetLastError();
         if (fehler == 0) break;
         Sleep(1000);
      }

   Sleep(100);
   Print("DLL: ", Kursdatenzeiger(kurse, Bars, 1, 4 ));
   Print("MT4: ", Close[1]);
     
   return(0);
  }


 
vostro1500:

I just removed the __stdcall recently. It does not make any difference.

When renaming RateInfo to KursInfo, did you keep the #pragma pack(push, 1) around the structure? I've tried your code, and I can't see any problems with it. Except that, unsurprisingly, it won't work if the #pragma is missing, and the definition of KursInfo is therefore different to what MT4 is using internally.
 

And there it is....


Thanks for your hint with "#pragma pack (...)" . Actually I had no clue what it means. Therefore I just forget to copy it. So now everything is working fine.

Obviously your an expert concerning Dlls ...:). So i'd like to ask you a second question.

Do you know how to get direct access to terminal information in MT4, Like AccountLeverage or AccountNumber? Or is the only possibility to get those information into the dll to pass them as a parameter in the mq4 code?

Thanks for your help!

 
vostro1500:

Thanks for your hint with "#pragma pack (...)" . Actually I had no clue what it means. Therefore I just forget to copy it. So now everything is working fine.

It controls the structure alignment, i.e. the actual layout in memory of the structure. The default in VS2010 (Configuration|C/C++|Code Generation|Struct Member Alignment) is 8 bytes (/Zp8). In other words, each member of KursInfo gets aligned on an 8-byte boundary; 8 bytes are set aside for holding the ctm value even though it only requires 4 bytes; and therefore the total size of the structure is 48 bytes. The #pragma pack(1) means that only 4 bytes are set aside for holding the ctm value, and therefore the total size of the structure is 44 bytes. It obviously causes a problem if MT4 is passing a block of memory where each record is 44 bytes long, but the DLL thinks that each record is 48 bytes long...


Do you know how to get direct access to terminal information in MT4, Like AccountLeverage or AccountNumber? Or is the only possibility to get those information into the dll to pass them as a parameter in the mq4 code?

As far as I am aware, you cannot obtain AccountLeverage() without relying on the MQ4 code passing the value to the DLL. There is a way of getting the account number without passing it from the MQ4 code, but I'm afraid I'm not going to publish it, because it would be possible for people to work round it if they knew that's how the DLL is getting the account number.

 

Ok I understand your concerns.

If there were easy access to this information in the internet it also would make no scence for me to use that possibility to protect my code.

Maybe I find the solution by myself...

 

Hi! It's me again.


At the moment I'm trying is to code functions in the dll which have access to the results of Kursdatenzeiger (GetRatesItemValue).

When I am doing this, the same problem occurs. That means the function returns no useful results. Probably because it does not consider the different types in the array.

In a handbook I've read that the "const"-declaration of the parameters can cause serious problem while parameter passing. So I just removed it but that's not the solution.

The direct access with e.g. "kursdaten[baranzahl-1-shift].close" also does not function.


    int __stdcall Funktionen::E_Open(KursInfo* kursdaten, int baranzahl)
    {
        if (MovingAvg(13,2,kursdaten, baranzahl)<MovingAvg(55,2,kursdaten, baranzahl) && MovingAvg(13,1,kursdaten, baranzahl)>MovingAvg(55,1,kursdaten, baranzahl)){
            return(1);
        }
        if ( MovingAvg(13,2,kursdaten, baranzahl)>MovingAvg(55,2,kursdaten, baranzahl) && MovingAvg(13,1,kursdaten, baranzahl)<MovingAvg(55,1,kursdaten, baranzahl)) {
            return(-1);
        }

        return(2);

    }
        double __stdcall Funktionen::MovingAvg(int period, int shift, KursInfo* kursdaten, int baranzahl)
        {
                double summe=0;
                for (int i=period+shift-1; i<=shift; i--){
                        double close=Kursdatenzeiger(kursdaten, baranzahl,4,1);
                        summe+=close;
                }
                double ergebnis= summe/period;
                return (ergebnis);
        }
        double  __stdcall Funktionen::Kursdatenzeiger(const KursInfo* kursdaten, const int baranzahl, const int auswahl, const int shift)
          {
        //----
           if(kursdaten==NULL)
                 {
                  printf("FEHLER: Leerer Array!\n");
                  return(1);
                 }
        //----
           if(baranzahl<=0)
                 {
                  printf("Fehler: Falsche Baranzahl! (%d)\n", baranzahl);
                  return(2);
                 }
        //----
           if(shift<0 || shift>=baranzahl)
                 {
                  printf("Fehler: Falscher Shift (%d)\n", shift);
                  return(3);
                 }
        //----
           if(auswahl<0 || auswahl>5)
                 {
                  printf("Fehler: Falscher Kursartindex (%d)\n", auswahl);
                  return(4);
                 }
        //----
           int Zeiger=baranzahl-1-shift;
           switch(auswahl)
                 {
                  case 0: return double(kursdaten[Zeiger].ctm);
                  case 1: return kursdaten[Zeiger].open;
                  case 2: return kursdaten[Zeiger].low;
                  case 3: return kursdaten[Zeiger].high;
                  case 4: return kursdaten[Zeiger].close;
                  case 5: return kursdaten[Zeiger].vol;
                 }
        //----
           return(5);
  }     

Thanks for your help!

Reason: