问题
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
回答1:
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 theAS_SERIES
flag). A function inside a DLL knows nothing about theAS_SERIES
flag, the passed array is a static array of an undefined length; an additional parameter should be used for specifying the array size.
来源:https://stackoverflow.com/questions/39520941/how-to-pass-argument-by-reference-from-mql4-to-c-dll