Вот мой код для MetaTraderWrapper.dll
:
#define MT4_EXPFUNC __declspec(dllexport)
MT4_EXPFUNC void __stdcall PopMessageString(wchar_t *message)
{
auto result = L"Hello world !";
int n = wcslen( result );
wcscpy_s( message, n + 1, result );
}
На стороне MQL4-Caller используется этот скрипт:
#property strict
#import "MetaTraderWrapper.dll"int PopMessageString( string & );
#import
//
void OnStart(){
string message;
if ( StringInit( message, 64 ) ){
PopMessageString( message );
int n = StringLen( message );
MessageBox( message );
}
}
Таким образом, это работает, когда message
были правильно инициализированы с StringInit()
функция и достаточно памяти было выделено.
Что мне нужно сделать, это выделить message
переменная не в скрипте MQL4, а внутри DLL.
В функции c ++ должно быть что-то вроде этого:
MT4_EXPFUNC void __stdcall PopMessageString(wchar_t *message)
{
auto result = L"Hello world !";
int n = wcslen( result );
// allocate here, but does not work
message = new wchar_t[n + 1]; // <--------- DOES NOT WORK
//
wcscpy_s( message, n + 1, result );
}
Что я могу сделать ?
string
быть string
( это struct
… с 2014 года) Внутреннее представление строкового типа представляет собой структуру длиной 12 байтов:
#pragma pack(push,1) struct MqlString { int size; // 32-bit integer, contains size of the buffer, allocated for the string. LPWSTR buffer; // 32-bit address of the buffer, containing the string. int reserved; // 32-bit integer, reserved. }; #pragma pack(pop,1)
Так,
Потрясенный этим солнечным воскресным днем, когда платформа претерпела LiveUpdate и внезапно все интерфейсы вызова DLL, использующие строку, перестали работать, потребовался долгий путь, чтобы покрыть расходы на такой «быстрый» технический сюрприз.
Вы можете повторно использовать найденное решение:
использовать массив байтов — uchar[]
и соответствующим образом конвертировать байты возвращаемого контента на стороне MQL4 в string
по сервисным функциям StringToCharArray()
соответственно CharArrayToString()
DLL-.mqh
-Заголовочный файл может также добавить эти уловки и сделать эти преобразования «скрытыми» из MQL4-кода:
#import <aDLL-file> // "RAW"-DLL-call-interfaces
...
// Messages:
int DLL_message_init( int &msg[] );
int DLL_message_init_size ( int &msg[], int size );
int DLL_message_init_data ( int &msg[], uchar &data[], int size );
...
#import
// ------------------------------------------------------ // "SOFT"-wrappers
...
int MQL4_message_init_data ( int &msg[], string data, int size ) { uchar dataChar[]; StringToCharArray( data, dataChar );
return ( DLL_message_init_data ( msg, dataChar, size ) );
}
Всегда будьте осторожны с соответствующими освобождениями, чтобы не вызвать утечек памяти.
Всегда будьте довольно вежливы, когда новый LiveUpdate меняет базу кода и вводит новый компилятор + новую документацию. Перечитайте всю документацию, так как многие жизненно важные данные попадают в файл справки только после следующего обновления, а многие детали скрыты или косвенно отражены в главах, которые не обещают такую информацию на первый взгляд, поэтому становятся готовый как Д’Артаньян или пионер в красном шарфе — вы никогда не знаете, откуда придет следующий хит 🙂
Других решений пока нет …