Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pass argument by reference from MQL4 to C++ DLL

Tags:

c++

dll

mql4

I am trying to write a simple program in MQL4 which passes a variable to a C++ DLL function by reference and prints the updated variable value in MQL4. Given below is my code.

DLL function:

void Test(int* X)
{
    *X = 6;
}

MQL4 Code

#import "Test.dll"
void Test(int&);
#import

void OnStart()
{
  int A;
  Test(A);
  Alert(A);
}

But I am not getting any value back from C++ function for variable A. Can someone please help me what I am doing wrong here?

Thanks in advance

like image 329
vikas Avatar asked Sep 15 '16 21:09

vikas


1 Answers

Let's start with the DLL-side:

int TestMoreApproachesAtONCE( int *X,
                              int *Y,
                              int  Z
                              )
{
    *X = 6;                   // 6 assigned to a 4B-memory chunk ref'd by *X
     Y = 6;                   // 6 assigned to a variable  Y
     return( Z );             // Z returned as a value passed from Caller
}

MQL4 requires DLL to have:

Functions imported DLL into a mql4-program must ensure the Windows API calls agreement. To ensure such an agreement, in the source text of programs written in C or C++, use the keyword __stdcall, which is specific to the Microsoft(r) compilers. This agreement is characterized by the following:

· caller (in our case it is a mql4-program) should "see" a prototype of a function called (imported from the DLL), in order to properly combine parameters to a stack;

· caller (in our case it is a mql4-program) puts parameters to the stack in a reverse order, from right to left - in this order an imported function reads parameters passed to it;

· parameters are passed by value, except those explicitly passed by reference (in our case strings)

· an imported function cleans the stack independently by reading parameters passed to it.

When describing the prototype of an imported function, default parameters can be used.

If the corresponding library is unable to load, or there is a prohibition on the DLL use, or the imported function is not found - the Expert Advisor stops its operation with the appropriate message "Expert Advisor stopped" in the Journal (log file). In this case the Expert Advisor will not run until it is reinitialized. An Expert Advisor can be reinitialized as a result of recompilation or after the table of its properties is opened and OK is pressed.

Now demonstrate the MQL4 side:

#import    "Test.dll" // -----------------------------------------------

                         void Test( int& );

                         int  TestMoreApproachesAtONCE( int &X,
                                                        int &Y,
                                                        int  Z
                                                        );
#import // "Test.dll" // -----------------------------------------------    

void OnStart()
{
     int A = EMPTY,
         B = EMPTY,
         C = EMPTY;
  // ---------------------------------------------------<PRE>
     Print( " TEST:: inital values are: A = ", A,
                                      " B = ", B,
                                      " C = ", C
                                      );
  // ---------------------------------------------------<TEST>

     C = TestMoreApproachesAtONCE( A, B, 6 );

  // ---------------------------------------------------<POST>
     Print( " TEST::  final values are: A = ", A,
                                      " B = ", B,
                                      " C = ", C
                                      );

}

Anyway, enjoy the Wild Worlds of MQL4 -- Also may enjoy to click and read other posts on issues in MQL4/DLL integration and/or signalling/messaging in MQL4 domains. Feel free to ask more

Finally, MQL4 Documentation states:

Passing Parameters
All parameters of simple types are passed by values unless it is explicitly indicated that they are passed by reference. When a string is passed, the address of the buffer of the copied string is passed; if a string is passed by reference, the address of the buffer of this string without copying it is passed to the function imported from DLL.

Structures that contain dynamic arrays, strings, classes, other complex structures, as well as static or dynamic arrays of the enumerated objects, can't be passed as a parameter to an imported function.

When passing an array to DLL, the address of the beginning of the data buffer is always passed (irrespective of the AS_SERIES flag). A function inside a DLL knows nothing about the AS_SERIES flag, the passed array is a static array of an undefined length; an additional parameter should be used for specifying the array size.

like image 179
user3666197 Avatar answered Sep 19 '22 00:09

user3666197