Return a structure out of a function without casting ??

 

Hello,

I want to return one whole structure by function. (simple include or class)

I`ve seen that there is a way by casting the thing. https://docs.mql4.com/basis/types/casting#casting_structure

Is there another way useable now in newer versions ? - May be like that (NOT WORKING !):

struct sTrade
  {
   string                        EaKontext;
   long                          myNumber;
   ulong                         order;
   string                        symbol;           // Trade symbol name
  };
  
sTrade retThis()
{
   sTrade test;
   return test;
}
// ERROR -> 'return' - structure have objects and cannot be copied


&sTrade retThis()
// ERROR -> '&' - expressions are not allowed on a global scope


It would be helpful, if I can deliver a pointer to the original structure...

Thanks for your ideas :-)

 
Abejorro:

Hello,

I want to return one whole structure by function. (simple include or class)

I`ve seen that there is a way by casting the thing. https://docs.mql4.com/basis/types/casting#casting_structure

Is there another way useable now in newer versions ? - May be like that (NOT WORKING !):


It would be helpful, if I can deliver a pointer to the original structure...

Thanks for your ideas :-)



Avoid strings in structures, replace them by a fixed-length char array.
 
Ovo:
Avoid strings in structures, replace them by a fixed-length char array.

Ok, this will fix my first problem: With that I can receive a whole structure ! - Many thanks for that hint !!

On the other hand, I`m still in the smell of casting. With my code using a uchar I need two functions for writing and reading the member. So it`s only a second away from writing a simple class for handling only data-structure.

struct sTrade
  {
   uchar                         EaKontext[12];
   long                          myNumber;
   ulong                         order;
   uchar                         symbol[20];           // Trade symbol name

   string                        getEaKontext();         // function forming a string for output
   void                          setEaKontext(string);   // function converting a string into this uchar
  };
  
string sTrade::getEaKontext(void)
   {
      string conv;
      // for (int i=0;i<=12;i++) {conv+=(string)EaKontext[i];}  // 2 errors here. thx gooly !
      for (int i=0;i<=11;i++) {conv+=CharToString(EaKontext[i]);}   // runing row !
      return conv;      
   }

void sTrade::setEaKontext(string tt)
   {
      // for (int i=0;i<StringLen(tt);i++) {EaKontext[i]=StringGetChar(tt, i);}   // missed the last character
      for (int i=0;i<=StringLen(tt);i++) {EaKontext[i]=StringGetChar(tt, i);}     // correct !
   }

  

sTrade retThis()
{
   sTrade test;
   
   //test.EaKontext = (uchar)"Content";
   //string op = (string)test.EaKontext;
   // ERROR -> 'EaKontext' - invalid array access
   // because of that missing functions has to be added to the structure...
   
   test.setEaKontext("lucky ?");
   string ot = test.getEaKontext();

   return test;
}


There is no smarter way ?

 

I would do define  a mqh-file with the struct and all its functions:

struct sTrade
  {
   uchar                         EaKontext[12];
   long                          myNumber;
   ulong                         order;
   uchar                         symbol[20];           // Trade symbol name
  };

string getEaKontext(sTrade &sT)
   {
      string conv;
      for (int i=0;i<=12;i++) {conv+=(string)EaKontext[i];}
      return conv;      
   }

void setEaKontext(sTrade &sT, string tt)
   {
      for (int i=0;i<StringLen(tt);i++) { sT.EaKontext[i]=StringGetChar(tt, i);}
   }

  

sTrade retThis( sTrade &test )
{
      
   //test.EaKontext = (uchar)"Content";
   //string op = (string)test.EaKontext;
   // ERROR -> 'EaKontext' - invalid array access
   // because of that missing functions has to be added to the structure...
   
   setEaKontext(test, "lucky ?");
   string ot = getEaKontext(test);

   return test;
}


As you can overload functions you are able to e.g. define in another mqh a function for sTrade with another struct.

What about if you define the strings globally in that mqh instead of struct-intern?

string sTrade_EAKontext, sTrade_Symbol;


PS: Are you sure that

conv+=(string)EaKontext[i];

is working? At least before b600+ we have to write:

conv =conv + (string)EaKontext[i];
 
gooly:

I would do define  a mqh-file with the struct and all its functions:

As you can overload functions you are able to e.g. define in another mqh a function for sTrade with another struct.

What about if you define the strings globally in that mqh instead of struct-intern?


PS: Are you sure that

is working? At least before b600+ we have to write:



1a) This is what I`m discussing with me. (I'm new in mql4 and MT4) A class-based-design with using structs in a module-include is not really straight. (Like a modul in VB.net) But if it fixes the issues... ok !

1b) Of course, one global variable will serve one value. But this EaKontext is going to describe much more the trading context, not the global name. On IB it`s easy to send bracket-orders. In MT4 you have to code for it. (the same with trailing-stops) This item may be helpful to check which order has which task. (Reload and changes in the orderlist are checked faster) Sure, THIS has not to be text !

2) First, the compiler was happy with the syntax ! But, you`re right. There are two errors at runtime ! I've changed it in the posting above with remarks so that there stays no false code. Thank's a lot for your skepticism :-)

(string) cast the figures to string (not wanted) So ->

string = CharToString(EaKontext[i]);

and that`s working. (checked in my build 765)

conv+=string;
 

Well the type cast of each single array element is now done within this function:

string = CharToString(EaKontext[i]);

To know what is faster you have to perform a speed test.

I found e.g. that

#define Pow2(a) ((a)*(a*))
...
double x = Pow2(M_LN2);
// is up to 42-times faster than
double y =  MathPow(M_LN2,2);
 
gooly:

Well the type cast of each single array element is now done within this function:

To know what is faster you have to perform a speed test.

I found e.g. that



faster than what ??

for (int i=0;i<=11;i++) {conv+=(string)EaKontext[i];}

Using this it comes with that: "10811799107121326300000". 

for (int i=0;i<=11;i++) {conv+=CharToString(EaKontext[i]);}

returns: "lucky ?"

And this is not available: return (string)EaKontext[];

I don`t like that loop but what else ?

 

ahh ok, I thought you original code was working.

But there is the mt4-function: CharArrayToString() - look it up in the editor's reference.

 
Abejorro: faster than what ??
double x = Pow2(a);
// is up to 42-times faster than
double y =  MathPow(M_LN2,2);
 
Abejorro:

Ok, this will fix my first problem: With that I can receive a whole structure ! - Many thanks for that hint !!

On the other hand, I`m still in the smell of casting. With my code using a uchar I need two functions for writing and reading the member. So it`s only a second away from writing a simple class for handling only data-structure.


There is no smarter way ?


Hi Abejorro. 

Everything depends on personal style, but for me it is not very useful to create data accessors within the structure itself, because you cannot hide the structure members from public access. In my code I expect structures to be pure data with no functionality.

For converting arrays and strings use the CharArrayToString, StringToCharArray,  StringToShortArray, ShortArrayToString. 

As far as you mentioned the structure casting, I think the guide explains coping data between different structure types rather than casting. Though MQL4 supports inheritance and casting of structures, using the casted structures confuses some native functions like FileWriteStruct()

 

@gooly: Yeah ! This is good stuff. There is a function CharArrayToString() and its sisters to convert without me to code a loop. I must have searched like a blind - and they do it better :-) Of course, this will be faster and smarter.

@WHRoeder: Thanks, I understood the example but didn`t see what the alternative in our discussion could be. (s.o.) And 42-times... Amazing !

@Ovo: This functions are really usefull. Now I have a workaround when a string-similar-type is necessary and I can return a structure by function !

Next is the test, if mql4 can reply an object by function like that here...And if there is plural inheritance like in c++ ?

But I`m not sure what you mean, that you can`t hide members. That is one good idea of OOP, or did I get you wrong ? I've coded my issue above to a next level using your suggestions and Polymorphism and 'Private': With that - I think - there is a simple way to prevent damages on data. You can see, there is no way to access the 'mEaKontext'-member. It's only possible using the 'property'-function and therein you can check if the things requested are allowed. On the other hand, I've not calculated what will happen on the RAM when each Data-item comes with a whole function-cocktail :-)


struct sTrade
  {
   private: 
      uchar                         mEaKontext[12];
   public: 
      ulong                         order;                 
      uchar                         symbol[20];             
      long                          deal_type;             
    
   string                        EaKontext();         // function forming a string for output
   void                          EaKontext(string);   // function converting a string into this uchar
  };
  
string sTrade::EaKontext(void) { return CharArrayToString(mEaKontext, 0);}

void sTrade::EaKontext(string tt) { StringToCharArray(tt, mEaKontext);}


// ----------------------------------


sTrade retThis()
{
   sTrade test;

   test.EaKontext("lucky ?");
   string ot = test.EaKontext();
   
   return test;
}




To me it looks good - thanks a lot !