Strange String behaviour
Results 1 to 8 of 8

Thread: Strange String behaviour

  1. #1
    Has anyone come across the next

    I've a script with the following declarations

    string symbol = XXXXXX;
    string open = Start; string stop = stop; string takeP = take;
    double Amounts[3];
    int Data[1];

    I then call a DLL Announced as follows

    Emptiness GetParmQuery(string symbol, string open, string stop, string takeP,
    double Amounts[], int Data[]);

    The values returned in the DLL are Anticipated ie the default values for symbol, open, stop and takeP Are changed But if I then do the next Evaluation

    if (open != start)
    Printing(NE);
    else
    Printing(EQ);

    the test fails and I get EQ printed

    Any ideas what is happening and can it be fixed without a messy work around

    Thank you

  2. #2
    Quote Originally Posted by ;
    if (open !) = start)
    Print(NE);
    else
    Print(EQ);

    the test fails and I receive EQ published
    Why don't you tell us what's included in the factor open following the call? Are you sure you could pass strings as pointers (as you clearly take action), have them altered in your DLL and still working in MT4 without producing an access violation? Can you alloe new memory for the new series in your DLL? Why don't you use string rather to be able to return the new pointer then? Who is responsible for freeing this newly alloed memory? And the question: Why on earth are you doing this with strings?

  3. #3
    Quote Originally Posted by ;
    Why don't you tell us what is found in the variable open after the call?
    Basically it may be whatever eg a series of 4 characters abcd


    Quote Originally Posted by ;
    Are you sure that you can pass strings as pointers (because you obviously take action), have them altered in your DLL and then still working in MT4 without creating an access violation?
    Well I don't have any AV's. And all works fine given I let sufficient memory for the factors in my script (ie that is the reason why I setup default values) at least as far as the returned values are worried It is the comparison function that is failing However something is obviously incorrect in my assumptions and might like to know if I can pass strings in this manner as I do with doubles and integers (like arrays however)

    Quote Originally Posted by ;
    Do you alloe new memory to the new series on your DLL?
    If I understand correctly I'm copying the information to the memory alloed by the script

    Quote Originally Posted by ;
    Why don't you use string rather to be able to return the new pointer then? Who's responsible for freeing this newly alloed memory?
    Utilizing series does give an AV and like I understand all memory is managed by the script



    Quote Originally Posted by ;
    And the main question: Why in the world are you doing so with strings at all?
    A bit confusing I agreebut I'm usiing the Levels array to pass the real worth The strings are for the following purpose altogether

  4. #4
    Quote Originally Posted by ;
    If I understand correctly I'm copying the information to the memory alloed with the script
    You can't be sure how metatrader handles strings internally. Perhaps your DLL will just get a pointer to some C compliant ( terminated) copy of the string that will be discarded after the call and it stores strings in an entirely different way. It's heap manager make clones for operations and will manage reference, perhaps they are Pascal strings and not C strings, or they used a string library that operates entirely with unicode or something like this. Who knows? It isn't documented anywhere! You are trying to manipulate metatrader's own data structures via an undocumented interface!

    Which are you really looking to do this can not be done the traditional way?

    Quote Originally Posted by ;
    somewhat confusing I agreebut I'm usiing the Degrees array to pass the real worth The strings are for another purpose entirely
    Can't it be encoded in integer worth? If these strings represent a limited number of commands or states then encode them. Establish a constant for each and every possible control or mode or state or whatever it's for much better readability, just like it's done in metatrader also: (OP_BUY, OP_SELL, MODE_FOO, MODE_BAR, etc.). Utilizing strings for things like that seems strange. There is a reason why this is not done such a manner. (except PHP maybe, because the PHP kiddies don't know what a constant is)

  5. #5
    Quote Originally Posted by ;
    What are you looking to do this can not be done the conventional way?
    So what is the conventional way to pass multiple series values back from a DLL (I use Delphi7 from the way) I take I could do a job around as you explain using integers but I had understood that sequences could be passed as pointers into the memory block see

    http://docs.mql4.com/basis/variables/extfunctions

    Thanks

  6. #6
    Quote Originally Posted by ;
    So what is the traditional way to pass several series values back out of a DLL (I use Delphi7 from the way) I take I can do a work around as you describe using integers but I'd known that strings might be passed as pointers into the memory block watch

    http://docs.mql4.com/basis/variables/extfunctions

    Due
    there's something written about pointers to memory blocks and something which sounds like Pascal strings, it doesnt make sense (maybe it makes more sense from the russian original) plus they dont discuss altering the series for later use by the mql4 script at all.

    What I can tell from my own experience is that strings passed to the DLL will simply be pointers to terminated strings. For this you would use a PChar form in Pascal. I've had one case where I ever felt the need to return a series from the dll into the script and that was when I wrote my own python binding. The function returning the value of a python string object to the calling mql4 script looks like this:

    Inserted Code function PyGetString(item : PPyObject) : #91;color=Red#93;PChar#91;/color#93;; stdcall; var gs : TGILState; begin gs := PyGILState_Ensure(); PyGetString := PyString_AsString(item); PyGILState_Release(gs); end;
    (You can find the full source code (Lazarus/FPC) attached as a .rar file in the end of the site: http://sites.google.com/site/prof/me...on-integration)

    The above will return a pointer to the series (made from the python DLL), just using the fuction return value. MT4 will copy the string in to it 's own memory from the pointer.

    Once I recommended the traditional way I was speaking to the traditional way for solving the issue, not the traditional way of returning strings. The traditional way of solving the problem (whatever it might be) would probably not include any use of strings returned into the script. Therefore here the question again?

  7. #7
    As 7Bit states you are manipulating memory that you (DLL) havent alloed and you also dont know how MQL deals with alloing memory into that string or the way that it stores its lively size (span)

    MQL

    String tstr;

    tstr = DLLreturnNullString();

    This works because MQL has been provided a pointer to a Term string ( that your DLL alloed memory to get) MQL then deals with alloing its own memory and internal alloion lists / string size listing and copies the data to the new MQL memory. Everythings good since you allow MQL build its own copy of the string.



    MQL

    String tstr;

    DLLchangethisString(tstr);

    This is dangerous for several reasons :

    A) you dont know how much memory (if any) MQL has alloed to the pointer your DLL recieves.
    B) If you change the string then MQL wont know it on it and if you alter the distance of it then MQL wont have updated its own 'knowlegde' of the length of the string
    C) should you attempt to change or read the string and above measure the memory that MQL alloed to it then you have a protection fault
    D) In my experience whilst MQL allows strings to be upto 64KB in size Im sure the memory isn't always aloed as one contiguous block of memory.


    If you do persist down this path (and id advise to not) the best way will be


    MQL

    int len;
    String tstr= ;
    // pad upto 255 characters in definition time so that memory has been alloed

    DLLchangethisString(len,tstr);
    Print(StringSubstr(tstr,0,len));

    This way your DLL passes back the new length of this string so you have some knowledge of its new span.



    I have noticed a C header that details the MQL chain structure (but have never used it) which alludes to how the string length is stored in an INT (4 Bytes) before the beginning of the string.
    So in your DLL you may try decrementing the String pointer supplied by MQL (by 4 bytes) and also writing an integer for the memory loion to specify the new length

    HOWEVER
    Ive never tried it / dont know when im right with this and that I wouldnt advise doing so because you are messing with MQL's knowledge of exactly what its done with this String should you alter its span from 255 to 10 then MQL might leak the memory that your DLL has made it ignorant of.

  8. #8
    OK Guys thanks for the help it appears the MQL docs are unclear. I'll now Concentrate on returning new strings in the DLL (as a Function call in Delphi) instead of altering existing ones and I'll look at restricting the usage of strings as long as 7Bit suggests

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
This website uses cookies
We use cookies to store session information to facilitate remembering your login information, to allow you to save website preferences, to personalise content and ads, to provide social media features and to analyse our traffic. We also share information about your use of our site with our social media, advertising and analytics partners.