MT5 build 1035 (x64) Вызов функции из DLL, возвращающей строку wchar_t* - страница 2

 
elugovoy:

Впервые слышу чтобы было некорректным возвращать указатель на строку из DLL.

Для того чтобы не углублялись в дебри "можно/нельзя" стандартный пример от MQ (входящий в поставку терминала 4):

Точно так же валит ошибку. 

Не так, а вот так:

MT4_EXPFUNC void __stdcall GetStringValue(wchar_t *spar)
  {
   *spar = L"content";
  }

Это на скорую руку, работать тоже не должно (вместо прямого присвоения нужно использовать wcscpy_s или memcpy_s). Смысл в том, чтобы возвращать строку через тот же параметр, через который был передан указатель на нее. 

 
Спасибо за сообщение. Нашли ошибку в x64, исправлено.
 
Scriptong:

Не так, а вот так:

Это на скорую руку, работать тоже не должно (вместо прямого присвоения нужно использовать wcscpy_s или memcpy_s). Смысл в том, чтобы возвращать строку через тот же параметр, через который был передан указатель на нее. 

Посмотрите стандартный пример из MT4, там именно такой метод:

MT4_EXPFUNC wchar_t* __stdcall GetStringValue(wchar_t *spar)
  {
   wprintf(L"Wide char string was received: \"%s\"\n",spar);
   return(spar);
  }

А вот Ваш *spar = L"content" как раз таки не станет переопределять длину строки, и если исходная строка была 3 символа (6 байт), то "content" - 14 байт будет затирать собой еще 8 байт.

Если же длина строки была больше, то тогда уж *spar = L"content\x00". Но такие конструкции в C не рекомендуются вовсе, так как отсутствует контроль над распределенной под переменные памятью.

Это можно использовать лишь для инициализации строки нужной длины, типа wchar_t *spar = "this is right\x00";

А вот функции копирования равно как и wprintf будут работать корректно. 

 
stringo:

Вы можете привести корректный пример с возвратом строки или альтернативу, если такого примера нет?

Все-таки тема все время актуальна.

 

Сообщение из SD:

Support Team 2015.01.14 09:42

Спасибо за сообщение, ошибка исправлена, исправление войдёт в ближайший билд. 

 
stringo:

Вам просто везло.

Некорректность заключается в попытке вернуть автоматически распределённую строку.

В отличие от MQL4/5, где строки являются базовым типом, в C/C++ строки не являются самостоятельным типом, а являются zero-terminated массивом символов.

Вы возвращаете указатель на массив, который после вызова функции автоматически уничтожается. Это - ошибка всех новичков (я тоже так ошибался)

Мы в свою очередь посмотрим, что мы такого поменяли, что перестал работать возврат строк...

Так и вспоминается поговорка... Герои нужны там где не хватает профессионалов.

Так вот. Дело вовсе не в везении. Тестировал и строки, определенные глобально и в shared секции DLL. В сервисдеск просто так не обращаюсь и кейсы на пустом месте не открываю.

Дело не в распределении памяти, а в том, что MT5 x64 не принимает строку UTF16 из DLL как принимает ее MT5 x32 и MT4.

Что ж вы за дурака-то меня держите, объясняя разницу в типах с которыми я лет 15 работаю, когда налицо ошибка MQ ?

Не стоит так относиться к людям.

Поскольку от СД получен конкретный ответ, тема закрыта. 

 
elugovoy:

Так и вспоминается поговорка... Герои нужны там где не хватает профессионалов.

Так вот. Дело вовсе не в везении. Тестировал и строки, определенные глобально и в shared секции DLL. В сервисдеск просто так не обращаюсь и кейсы на пустом месте не открываю.

Дело не в распределении памяти, а в том, что MT5 x64 не принимает строку UTF16 из DLL как принимает ее MT5 x32 и MT4.

Что ж вы за дурака-то меня держите, объясняя разницу в типах с которыми я лет 15 работаю, когда налицо ошибка MQ ?

Не стоит так относиться к людям.

Поскольку от СД получен конкретный ответ, тема закрыта. 

Никто Вас за дурака не держит. Но то, что Вы, работая 15 лет с разными типами данных, не знаете базовых вещей - непозволительная роскошь для программиста.

Объясните мне, пожалуйста, что не так в моём отношении к людям. Если здесь стесняетесь, то можно в личку. Что я такого сказал? Я назвал Вас новичком? Так Вы им до сих пор и являетесь. Мы все - новички. Je suis un débutant в этом мире

Мы свою ошибку исправили. А Вы - как хотите. Можете не исправлять. Надейтесь и дальше на текущую реализацию Вашего компилятора.

 
TheXpert:

Вы можете привести корректный пример с возвратом строки или альтернативу, если такого примера нет?

Все-таки тема все время актуальна.

Более устойчивый пример. Строка живёт, пока загружена dll

wchar_t* returned_string=L"Wide char string was returned successful. Test Passed\x00";

// return UTF-16 string
MT4_EXPFUNC wchar_t* __stdcall TestTheString()
  {
   return(returned_string);
  }

Если же строка должна быть сформирована в зависимости от вызова, то её нужно формировать в памяти, существующей до вызова. И иметь в виду, что эта память будет неизменна только до следующего вызова

wchar_t returned_string[256]={0};

// return UTF-16 string
MT4_EXPFUNC wchar_t* __stdcall TestTheString()
  {
   wcscpy_s(returned_string,L"Wide char string was returned successful. Test Passed\x00");
   return(returned_string);
  }
 
stringo:

Никто Вас за дурака не держит. Но то, что Вы, работая 15 лет с разными типами данных, не знаете базовых вещей - непозволительная роскошь для программиста.

Объясните мне, пожалуйста, что не так в моём отношении к людям. Если здесь стесняетесь, то можно в личку. Что я такого сказал? Я назвал Вас новичком? Так Вы им до сих пор и являетесь. Мы все - новички. Je suis un débutant в этом мире

Мы свою ошибку исправили. А Вы - как хотите. Можете не исправлять. Надейтесь и дальше на текущую реализацию Вашего компилятора.

Объясняю.

Во-первых, если тема открыта по одной проблеме, не нужно пытаться уводить ее в другую сторону. Достаточно проверить и признать - да, наша ошибка, исправим. А не разводить демагогию об объявлении переменных.

Во-вторых, Специально для демонстрации ошибки была взята функция, определенная в поставке MT4 в файле <MT4 home>\MQL4\Scripts\Examples\DLL\DLLSample.cpp

MT4_EXPFUNC wchar_t* __stdcall GetStringValue(wchar_t *spar)
  {
   wprintf(L"GetStringValue takes \"%s\"\n",spar);
   return(spar);
  }

Так что это Ваш пример (MetaQuotes), а не мой и на счет непозволительной роскоши - это к вашим ребятам обращайтесь. У меня переменные определяются на глобальном уровне и за выделением памяти я слежу.

Если Вы его считаете некорректным по каким-либо причинам, так замените его в поставке MT4 на корректный. 

В-третьих, на счет "Надейтесь и дальше на текущую реализацию Вашего компилятора". Может Вы вкладываете иной смысл в термин "компилятор", но я компилятор и не разрабатываю вовсе, если Вы имеете ввиду компилятор MetaEditor, так Вы же (MQ) его и разрабатываете. 

Исходя из вышесказанного, создается впечатление что у MQ как и у некоторых его представителей напрочь отсутствует уважение к сообществу разработчиков MQL.

 

Вы так и не поняли. Я указал на проблему именно в Вашем коде

// return UTF-16 string
MT4_EXPFUNC wchar_t* __stdcall TestTheString()
{
 return (L"Wide char string was returned successful. Test Passed\x00");
}

В текущей реализации Вашего компилятора просто возвращается ссылка на область константных строк. Область константных строк в текущей реализаци Вашего компилятора постоянно загружена в память и постоянно доступна.

Повторяю - это именно благодаря текущей реализации Вашего компилятора, которая несколько противоречит стандарту C++, ибо Вы оперируете с автоматическими локальными переменными, время жизни которых - от момента объявления до выхода из блока.

Причина обращения: