Пример.
Скрипт для теста
#property copyright "Copyright 2015, MetaQuotes Software Corp." #property link "https://www.mql5.com" #property version "1.00" #import "test.dll" string TestTheString(); #import void OnStart() { Print ("Testing the string, returned by DLL!"); string result; result = TestTheString(); Print(result); Print ("Done!"); }
Исходник DLL
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers #define MT4_EXPFUNC __declspec(dllexport) #define _USE_INLINING #define TRACE #include <windows.h> #include <stdlib.h> #include <stdio.h> // just for compatibility BOOL APIENTRY DllMain(HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved) { switch(ul_reason_for_call) { case DLL_PROCESS_ATTACH: break; case DLL_THREAD_ATTACH: break; case DLL_THREAD_DETACH: break; case DLL_PROCESS_DETACH: break; } return(TRUE); } // return UTF-16 string MT4_EXPFUNC wchar_t* __stdcall TestTheString() { return (L"Wide char string was returned successful. Test Passed\x00"); }
Скриншот ошибки
Прикреплен архив со скриптом и DLL.
А что так можно? По-моему такой код в принципе некорректен.
А что так можно? По-моему такой код в принципе некорректен.
В чем некорректность?
В MT4 начиная с 600 билда по сей день выполняется корректно. В MT5 тоже, до билда 1035.
Пробовал обернуть в структуру MqlStr c длиной строки и самой строкой - реакция та же.
Определял глобальную строковую константу - результат тот же.
Выставил самый простой вариант, который и использовался ранее всегда и работал прекрасно.
Под x64 проект DLL компилировал в режимах MULTI BYTE и UNICODE, результат одинаков.
Я вообще всегда тщательно подхожу к отладке и проверке; и прежде чем в сервисдеск обращаться стараюсь как можно больше тестов провести самостоятельно.
В чем некорректность?
В том кто управляет памятью строки. Вы передаете указатель на литерал, а терминал по логике должен этот участок памяти освободить.
Могу ошибаться конечно, поэтому хочется услышать комментарий разработчиков.
В том кто управляет памятью строки. Вы передаете указатель на литерал, а терминал по логике должен этот участок памяти освободить.
Могу ошибаться конечно, поэтому хочется услышать комментарий разработчиков.
Терминал не должен заботиться о распределении памяти во внешних ресурсах. Другое дело, когда в DLL определяется локальная переменная, указатель на которую возвращается в MQL, а затем (при выходе из функции) происходит высвобождение памяти, выделенной под эту переменную.
Тогда MQL получит ссылку на часть памяти, как говорится "бывшей в употреблении". Ссылка на константу же будет ликвидной даже при выходе из функции (при загрузке DLL будет выделен участок памяти для константы и функция вернет адрес начала строки, во всяком случае в ассемблере именно так обстоят дела).
А что так можно? По-моему такой код в принципе некорректен.
Впервые слышу чтобы было некорректным возвращать указатель на строку из DLL.
Для того чтобы не углублялись в дебри "можно/нельзя" стандартный пример от MQ (входящий в поставку терминала 4):
MT4_EXPFUNC wchar_t* __stdcall GetStringValue(wchar_t *spar) { wprintf(L"Wide char string was received: \"%s\"\n",spar); return(spar); }
Точно так же валит ошибку.
В чем некорректность?
В MT4 начиная с 600 билда по сей день выполняется корректно. В MT5 тоже, до билда 1035.
Пробовал обернуть в структуру MqlStr c длиной строки и самой строкой - реакция та же.
Определял глобальную строковую константу - результат тот же.
Выставил самый простой вариант, который и использовался ранее всегда и работал прекрасно.
Под x64 проект DLL компилировал в режимах MULTI BYTE и UNICODE, результат одинаков.
Я вообще всегда тщательно подхожу к отладке и проверке; и прежде чем в сервисдеск обращаться стараюсь как можно больше тестов провести самостоятельно.
Вам просто везло.
Некорректность заключается в попытке вернуть автоматически распределённую строку.
В отличие от MQL4/5, где строки являются базовым типом, в C/C++ строки не являются самостоятельным типом, а являются zero-terminated массивом символов.
Вы возвращаете указатель на массив, который после вызова функции автоматически уничтожается. Это - ошибка всех новичков (я тоже так ошибался)
Мы в свою очередь посмотрим, что мы такого поменяли, что перестал работать возврат строк...
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
Столкнулся вот с такой проблемой.
При вызове тривиальной функции из DLL, которая возвращает строку, MT5 валит ошибку "Access violation"
Причем если скрипт был скомпилирован в одном из предыдущих билдов, то он работает нормально. Если же перекомпилировать в 1035, то получается вот такая беда.
Такой ощущение что x64 не UTF-16 использует уже а что-то другое, хотя тот же билд 1035 x86, работает вроде как нормально.
Кто-то сталкивался еще с подобным ?
Открыл кейс в сервис деск по этому поводу.