MQL4 help needed: Access to class members in an array

Post Reply
User avatar
degoor1975
Posts: 3
Joined: Thu Aug 29, 2019 8:05 pm
Location: Ruse, Bulgaria

MQL4 help needed: Access to class members in an array

Post by degoor1975 »

I started to write an EA for the Empty4 platform and got stuck using class members in MQL4.

I come from C# background where that thing is really easy to do. Hope someone will help me doing that in MQL4.

So suppose I have a small class called #PivotPoint that has members called #Index & #PP.

Then I would like to create an array from 6 instances of the #PivotPoint class and in the body of the EA I need to add and update those instances. After that {for testing purposes} I need to create dot objects on a chart from those pivot points.

Here is a sample of my code:

Code: Select all

bool doDots = true;
string obj_name = "dot";
long current_chart_id;

class PivotPoint
{
    public:
        int Index;
        double PP;
        
        // Default constructor
        PivotPoint(void){};
        // Parametric constructor
        PivotPoint(int index, double pp)
        {
            Index = index;
            PP = pp;
        };
};

// create chain of 6 pivot points for the fork chain
PivotPoint *fork_chain[6];

// counter for the elements added in *fork_chain
int fork_counter = 0;

void OnStart()
{
    int index_ = iBars(_Symbol, _Period);
    double high_ = iHigh(_Symbol, _Period, 1);
    
    // increment #fork_counter
    fork_counter++;

    // add the result to #fork_chain
    add_new_pivot(fork_chain, index_, high_, fork_counter);
    
    // create new fork PivotPoint
    PivotPoint *new_pp = new PivotPoint(index_, high_);
    
    if(doDots == true)
    {
        draw_dot(obj_name + IntegerToString(new_pp.Index), 
            new_pp.Index, new_pp.PP);
    }
}


void add_new_pivot(PivotPoint* &arr_pp[], int index_, double high_, 
    int counter)
{
    ///<summary>Adds new #PivotPoint instance to a #PivotPoint
    /// _ list.</summary>
    
    // find array size
    int len = ArraySize(arr_pp);

    PivotPoint pp_ = new PivotPoint(index_, high_);
    
    if(counter <= len)
    {
        //// ------- Compilable in MetaEditor (MQL4, 5.00 build 2375)
        //// ------- Error "invalid pointer access" on row 65 in Empty4
        //arr_pp[counter - 1] = pp_;
        arr_pp[counter - 1].Index = pp_.Index; // row 65
        arr_pp[counter - 1].PP = pp_.PP;
    }
        
    else
    {
        ArrayResize(arr_pp, len + 1);
        //arr_pp[len] = pp_;
        arr_pp[len].Index = pp_.Index;
        arr_pp[len].PP = pp_.PP;                        
        EraseOrdered(arr_pp, 0);
    }        
}


template <typename T> void EraseOrdered(T& A[], int iPos)
{
   ///<summary>Deletes certain index number from an array.</summary>
   
   int iLast;
   for(
      iLast = ArraySize(A) - 1; 
      iPos < iLast; 
      ++iPos
      )
   {
      A[iPos] = A[iPos + 1];
   }
      
   ArrayResize(A, iLast);
}


void draw_dot(string objName, int dt_index, double price)
{
   ///<summary>Draw dot object on the chart.</summary>

   ObjectCreate
      (
      objName + (string)Time[dt_index],   // object name
      OBJ_TEXT,                           // object type 
      0,                                  // window index
      Time[dt_index],                     // time of the first anchor point
      price                               // price of the first anchor point
      );    
   ObjectSetText
      (      
      objName + (string)Time[dt_index], 
      CharToStr(159), 
      14,                  // size of the font
      "Wingdings",         // name of the font
      Red                  // color of the dot
      );
}
As commented in the code listing I can compile that but when started on a Empty4 chart I get "invalid pointer access" error on line 65.

Obviously I can't access the members of the PivotPoint class in the array the way I am trying to. Hope you can give me a hand on that.

Technically in the code above I can add new instance of the PivotPoint class and later draw the dot by only using #index_ and #high_. The problem is that later in my code {not included here} I need to update a previous instance of that class in the array so I still need to be able to access the members of that previous instance.

EDIT:
I have missed to include a line in #OnStart about #current_chart_id variable:

Code: Select all

if(doDots == true)
        current_chart_id = ChartID()
but that is not essential for my question :)
In trading as in life you need to learn only from the best!
User avatar
renexxxx
Trader
Posts: 860
Joined: Sat Dec 31, 2011 3:48 am

MQL4 help needed: Access to class members in an array

Post by renexxxx »

In order to avoid the "invalid pointer access" runtime error, you need to use the CheckPointer and GetPointer functions, as described in the docs.

Besides, if you want to create an array of object pointers, it is much easier to use the CArrayObj class included with Empty4, eg. like this:

Code: Select all

#include <Arrays/ArrayObj.mqh>

bool doDots = true;
string obj_name = "dot";
long current_chart_id;
 
class PivotPoint : public CObject
{
    public:
        int Index;
        double PP;
       
        // Default constructor
        PivotPoint(void){};
        // Parametric constructor
        PivotPoint(int index, double pp)
        {
            Index = index;
            PP = pp;
        };
};
 
// create chain of pivot points for the fork chain
CArrayObj fork_chain;
 
void OnStart()
{
    int index_ = iBars(_Symbol, _Period);
    double high_ = iHigh(_Symbol, _Period, 1);
   
    PivotPoint *new_pp = new PivotPoint( index_, high_ );    

    fork_chain.Add( new_pp );;
   
    if(doDots == true)
    {
        draw_dot(obj_name + IntegerToString(new_pp.Index),
            new_pp.Index, new_pp.PP);
    }
    
    fork_chain.Shutdown();
}
 
void draw_dot(string objName, int dt_index, double price)
{
   ///<summary>Draw dot object on the chart.</summary>
   
   if ( dt_index < Bars ) {
 
      ObjectCreate
         (
         objName + (string)Time[dt_index],   // object name
         OBJ_TEXT,                           // object type
         0,                                  // window index
         Time[dt_index],                     // time of the first anchor point
         price                               // price of the first anchor point
         );    
      ObjectSetText
         (      
         objName + (string)Time[dt_index],
         CharToStr(159),
         14,                  // size of the font
         "Wingdings",         // name of the font
         Red                  // color of the dot
         );
      }
}
I have no clue what your code is supposed to do and whether the above code does just that, but hopefully it helps.
User avatar
degoor1975
Posts: 3
Joined: Thu Aug 29, 2019 8:05 pm
Location: Ruse, Bulgaria

MQL4 help needed: Access to class members in an array

Post by degoor1975 »

renexxxx, thanks for your answer.

It turned out that the solution to my question is really simple:
1. When I need to create an instance of a class {as in the code above} I should do that like:

Code: Select all

ClassName *classInstance;
2. When I need to create an array from class instances {new here} I should code:

Code: Select all

ClassName arrayClassInstance[6];
3. When I need to put an array from class instances as function parameter {also new here} I should code:

Code: Select all

void functionName(ClassName &arrayClassInstance[], ...){...}
In trading as in life you need to learn only from the best!
Post Reply

Return to “Know your MT4 platform”