[...] Where is the problem ?
Strings are not passed to a DLL using MT4's internal MqlString structure. They are simply passed as a pointer (to a Unicode string). Therefore, the function definition should be:
_DLLAPI int __stdcall fn_Test_stringMT4(LPWSTR mystringmt4)
From https://docs.mql4.com/runtime/imports:
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.
(This means that strings passed to DLLs cannot contain null characters, and do not have an explicit size. If you need the size, then you simply use wcslen or lstrlenW in the usual way.)
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.
ok but is it sure that buffer means the buffer of the string in the struct in mql ? or buffer means the pointer on the structure.
because on https://www.mql5.com/en/articles/1391 they said in 2.4. Unicode strings and their use in a DLL: The internal structure of strings has changed in MQL4 (now it takes 12 bytes), and the MqlString structure should be used when passing strings to DLL.
and the link on MqlString is https://www.mql5.com/ru/forum/150672. It seems they use the mqlstring structure in their dll.
That bit of documentation is wrong. And it makes no sense: if MT4/MT5 passed strings as a MqlStr structure then it would be impossible to call Win32 functions which expect strings to be passed as char*/wchar*.
[EDIT...]
MT4/MT5 don't in fact just pass a pointer to a string buffer. The four bytes below the string contain the int size of the number of characters in the string.
In other words, using the following MQL4 code...
#import "MyDll.dll" void Test(string); #import void OnStart() { string x = "ABCDEF"; Test(x); }
... you can then do the following in a DLL:
extern "C" void __stdcall Test(WCHAR * x) { // Get the string length which is contained in an int in the four bytes // immediately preceding the string pointer referenced by x int lStringLength = *(((int*)x) -1); WCHAR tmp[30]; _swprintf(tmp, L"String length: %i", lStringLength); MessageBoxW(NULL, x, tmp, 64); }
But getting the string length this way is not what is documented at https://docs.mql4.com/runtime/imports, and it could potentially break in future. MT4/MT5 could simply start passing a WCHAR* without breaching the documentation.
For confirmation, MT4/5 is not passing a MqlStr structure. MqlStr is as follows:
int size; WCHAR * buffer; int reserved;
What MT4/5 are passing to a DLL is:
int size; WCHAR buffer[];
... with the pointer which the DLL receives being the address of the buffer member, not the address of the size member. It's very like a Windows BSTR in that respect.
Hello,
Thank you for your informations, they helped me a lot.
I'm writing a dll for mt4 version 4.00 build 1170.
When I use stdcall I encounter stack problem, with cedecl it works, this is not what I read in forums. Did it change, do you know sometingabout that ?
Janfi
Hello Alain,
I don't need help, my dll works perfectly, I'm just surprised to see that in the forums everyone said to use stdcall for calling dll functions, instead of cedecl, and it's wrong.
They were old articles, maybe MetaQuote changed in new versions. Also for passing strings, they were 1 byte per char and now they are 2 bytes per char.
Janfi
Hello Alain,
I don't need help, my dll works perfectly, I'm just surprised to see that in the forums everyone said to use stdcall for calling dll functions, instead of cedecl, and it's wrong.
They were old articles, maybe MetaQuote changed in new versions. Also for passing strings, they were 1 byte per char and now they are 2 bytes per char.
Janfi
You said "cdecl" works where "stdcall" doesn't and asked for information about that.
The mql4 (and mql5) compiler is supposed to work with both. So my request for code to see why in your case it works with cdecl only.
From this article (by MetaQuotes CEO) :
The DLL imported functions calls in MQL5 should have the stdcall and cdecl calling convention. Though stdcall
and cdecl differ in the ways of parameter extracting from a stack, the
MQL5 runtime environment can safely use both versions because of the
special wrapper of DLL calls.
The C++ compiler uses
__cdecl calling by default, but I recommend explicitly specifying the __stdcall mode for exported functions.
and
Forum on trading, automated trading systems and testing trading strategies
Chat with developers via Service Desk!
Renat Fatkhullin , 2015.03.19 13:57
And what are the problems with the import?
Everything works normally under x64 conventions (they are different with respect to 32 bits and are strictly standardized).
There are no problems at all. And even in 32 bits, there are no problems with different cdecl / stdcall calls. Due to our protective wrapper MQL4 / MQL5, we don’t care what the agreement of the imported function is.
- devblogs.microsoft.com
The problem comes maybe because I wrote the dll with FreePascal, I'm a Linux user and I don't have many Windows tools.
I don't need help, my dll works perfectly, I'm just surprised to see that in the forums everyone said to use stdcall for calling dll functions, instead of cedecl,
stdcall is a calling convention for VB6, VBA;
cdecl - for c++;
and 1 was used, not both;
but as so as now C# & VB are in .NET, & they have easy communication/understanding each other inside .NET environment, & most soft (perhaps something in MT) use .NET libs (even CLI C++ libs) - thus, this can explain the fact that boundary between cdecl & stdcall like not exist... imho... and you get lucky to use any
- Free trading apps
- Over 8,000 signals for copying
- Economic news for exploring financial markets
You agree to website policy and terms of use
Hi,
To pass mql4 string to dll in C I see this articles:
https://docs.mql4.com/basis/types/stringconst
https://www.mql5.com/en/articles/1391
so in my dll I do this :
and in mql4 :
When I print the string in mql4 I have the output: EURUSD
but when I print in C I have the ouput :
Symbol = TEST_Symbol, Size = 6619242, reserved = 7536741 MQLSTring = RUSD, Size = 6619242, reserved = 7536741
the first 2 characters of my mql4 string are not printed. I have RUSD instead of EURUSD
Where is the problem ?