... принимать в советник данные из внешней библиотеки (DLL) ... объявляю массив инициализированных строковых переменных достаточного для размещения параметров размера ... при первом вызове внешней функции в эксперте успешно получаю данные через этот массив ... при повторном использовании массива строки "теряют" свои буферы - в DLL принимается строка с нулевой длиной ... каким образом можно восстанавливать буфер для string (в MQL, в DLL)? ... может быть есть другой безопасный способ повторного использования строковых переменных для получения данных их внешних библиотек?
... принимать в советник данные из внешней библиотеки (DLL) ... объявляю массив инициализированных строковых переменных достаточного для размещения параметров размера ... при первом вызове внешней функции в эксперте успешно получаю данные через этот массив ... при повторном использовании массива строки "теряют" свои буферы - в DLL принимается строка с нулевой длиной ... каким образом можно восстанавливать буфер для string (в MQL, в DLL)? ... может быть есть другой безопасный способ повторного использования строковых переменных для получения данных их внешних библиотек?
Поиск рулит
вот пример похожей проблемы
https://forum.mql4.com/ru/12812
вот пример похожей проблемы
https://forum.mql4.com/ru/12812
Спасибо, прочитал. У меня вроде бы так и сделано, как рекомендовано.
Проблемы с возвратом строковых параметров у меня вроде бы нет - приложение не валится, параметры передаются.
Есть проблема с повторной инициализацией (присваиванием) строки в MQL. Я объявляю массив строк в глобальном пространстве имен (MQL).
//static string params[3] = {
string params[3] = {
"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111",
"22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222"
};
После этого передаю этот массив в DLL и получаю значения.
if ( true == GetParams( params, ArraySize(params) ) )
{
...
}
По окончанию обработки очищаю массив строк от старых значений (похоже в этом месте я и совершаю ошибку - не правильно очищаю строковые переменные., после этого присваивания строки обнуляются).
// reinit array
params[0] = "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
params[1] = "11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111";
params[2] = "22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222";
Является ли допустимым такое присваивание значения инициализированной MQL строке? Или так делать нельзя и нужно использовать оператор + (функцию StringConcatenate()), переписывая буфер начиная с первого символа? Не произойдет ли при этом сброс ранее выделенного буфера? Можно ли будет при этом увеличить размер буфера (не будет ли переполнения)?
Я написал простой проверочный скрипт, и он показал, что MQL4-функции конвертации строковых значений не меняют содержимое.
//+------------------------------------------------------------------+ //| CheckStringArray.mq4 | //| Copyright © 2007, MetaQuotes Software Corp. | //| http://www.metaquotes.net | //+------------------------------------------------------------------+ #property copyright "Copyright © 2007, MetaQuotes Software Corp." #property link "http://www.metaquotes.net" //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void testFunction(bool show) { //---- static string params[3] = { "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111", "22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222" }; int cmd = StrToInteger(params[0]); double volume = StrToDouble(params[1]); double price = StrToDouble(params[2]); if (show) { Print("1 StringLen()=",StringLen(params[0])," string:",params[0]); Print("2 StringLen()=",StringLen(params[1])," string:",params[1]); Print("3 StringLen()=",StringLen(params[2])," string:",params[2]); } else { int f = StringLen(params[0]); int s = StringLen(params[1]); int t = StringLen(params[2]); if (f!=s || s!=t || f==0) Print(params[0],"|",params[1],"|",params[2]); } //---- return; } //+------------------------------------------------------------------+ //| script program start function | //+------------------------------------------------------------------+ int start() { //---- Print("Первый"); testFunction(true); Print("Второй"); testFunction(true); for (int i=0; i<1000000;i++) { testFunction(false); Comment(i); Sleep(50); } //---- return(0); } //+------------------------------------------------------------------+
Вы можете предоставить свой код? Это ускорило бы нахождение истины.
ваша проблема, скорее всего в некорректной DLL
но возможно и в некорректном коде MQL4
без кода понять будет сложно!
---
если DLL на паскале - делфи, не скажу ничего...
если на Си то вероятно подскажу
пишу в Си
Я написал простой проверочный скрипт, и он показал, что MQL4-функции конвертации строковых значений не меняют содержимое.
for (int i=0; i<1000000;i++) { testFunction(false); Comment(i); Sleep(50); }
В своем коде Вы не используете повторную инициализацию (присвоение значений) для string params[3].
В моем же коде после использования строкового массива я пытаюсь затереть старые значения "очистить заполнителями" - записываю нули, единицы и т.д.
Поскольку код моего эксперта не помещается в сообщение форума, я выложил его на сайте http://homeauto.com.ua/Software/MetaBridgeSetup.msi
Куцая инструкция как им пользоваться лежит там же http://homeauto.com.ua/Software/MetaBridge_manual.doc
Код моего эксперта тестирует совместную работу MetaTrader, Excel и eSignal.
Спасибо за помощь!
Все заработало после того, как я почистил код своей DLL. Видимо где-то гулял указатель и портил память. Похоже из-за этого оператор присваивания в советнике не срабатывал:
"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
};
switch(functionId[0])
{
case MarketInfoId:
{
int type = StrToInteger(params[0]);
}
}
Print("Init params[0] = ", params[0]);
params[0] = "x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
2008.06.09 11:27:29 MetaBridge GBPUSD,H4: reinit array
В строке лога '2008.06.09 11:27:29 MetaBridge GBPUSD,H4: Init params[0] = ' видно что оператор присваивания не инициализирует строку (ее длина становится нулевой, хотя до инициализации она содержала значение).
Print("reinit array");
params[0] = "x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
Print("Init params[0] = ", params[0]);
ЗЫ. Попутно выяснилось, что можно спокойно увеличивать размер строки против инициализированной в массиве - в DLL передается буфер увеличенного размера. Не выяснял, правда, как это работает в реале.
Все заработало после того, как я почистил код своей DLL. Видимо где-то гулял указатель и портил память. Похоже из-за этого оператор присваивания в советнике не срабатывал:
"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
};
switch(functionId[0])
{
case MarketInfoId:
{
int type = StrToInteger(params[0]);
}
}
Print("Init params[0] = ", params[0]);
params[0] = "x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
2008.06.09 11:27:29 MetaBridge GBPUSD,H4: reinit array
В строке лога '2008.06.09 11:27:29 MetaBridge GBPUSD,H4: Init params[0] = ' видно что оператор присваивания не инициализирует строку (ее длина становится нулевой, хотя до инициализации она содержала значение).
Print("reinit array");
params[0] = "x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
Print("Init params[0] = ", params[0]);
ЗЫ. Попутно выяснилось, что можно спокойно увеличивать размер строки против инициализированной в массиве - в DLL передается буфер увеличенного размера. Не выяснял, правда, как это работает в реале.
Ostap, как с вами связаться ? Есть некая мысля по поводу MetaBridge.
> Ostap, как с вами связаться ? Есть некая мысля по поводу MetaBridge.
Пишите на vroma at users.sourceforge.net - мне перешлют (не хочу светить свое мыло спамерам).
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
Добрый день!
Мне нужно принимать в советник данные из внешней библиотеки (DLL). Для этого объявляю массив инициализированных строковых переменных достаточного для размещения параметров размера, заполняю их данными (как было рекомендовано в одной из тем этого формума):
static string params[3] = {
"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111",
"22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222"
};
Во внешней библиотеке принимаю указатель на MqlStr, заполняю массив
MqlStr* paramsArray
strcpy( paramsArray[i].string, pMyParamsStr->c_str() );При первом вызове внешней функции в эксперте успешно получаю данные через этот массив, строки имеют необходимую длину, они корретно преобразуются в нужный тип:
int cmd = StrToInteger(params[0]);
double volume = StrToDouble(params[1]);
double price = StrToDouble(params[2]);
После этого повторно использую массив params[3] при вызове все той же функцуии в DLL.
При этом мне нужно, чтобы строковыйо массив сохранил свою инициализацию (строки имели выделенные буферы чтобы я не управлял памятью для размещения данных, передаваемых в метатрейдер из внешней библиотеки). Но, к сожалению, при повторном использовании массива строки "теряют" свои буферы - в DLL принимается строка с нулевой длиной.
paramsArray [i]. len == 0,
также
strlen(paramsArray[c].string) == 0
При этом указатель на буфер не обнулен
paramsArray[i].string != NULL
Пробовал играться модификатором static - ничего не меняется, буфер все равно обнуляется.
Из этого я сделал вывод, что после выполнения функции преобразования строковых данных (использования переменной?) используемый буфер обнуляется. После выполнения функции
int cmd = StrToInteger(params[0])
устанавливается
params[0].len == 0 и
params[0].string == 0
Подскажите, пожалуйста, каким образом можно восстанавливать буфер для string? Или может быть есть другой безопасный способ повторного использования строковых переменных для получения данных их внешних библиотек?
ЗЫ. Использую MetaTrader 4.0 Build 216.