Непонятки с массивами строк - страница 2

 
Да, было что-то подобное - Crash в "About"
 
elritmo:

то есть если хотим передавать строки в эксперт из DLL то надо заранее проинициализировтаь строки максимальным значением типа

Да, только так. К сожалению, по другому со строками работать не получится.
 
Renat:
elritmo:

то есть если хотим передавать строки в эксперт из DLL то надо заранее проинициализировтаь строки максимальным значением типа

Да, только так. К сожалению, по другому со строками работать не получится.
Ренат, да такой метод меня бы устроил, главно чтобы он не приводил со временем к утечке памяти и падению терминала
Должен ли я также указать длину строки как указано в коде ниже или достаточно скопировать новую строку в strArray[n].string в которой зарезервировано максимальное количество байт под символы?
Терминал потом не упадет в дальнейшем из-за того, что длина строки заканчивающаяся нулём у него изменилась внутри длл, а len не была модифицирована в длл?

EXP void __stdcall dllFunc(MqlStr* strArray, int n) {
  strcpy(strArray[0].string, "maximum 14 char");
  strArray[0].len = 14;
  strcpy(strArray[1].string, "123");
  strArray[1].len = 3;
}
Ну а что терминал потом сам узнает что у него длина строки поменялась в dll без изменения len? Не случится ли так что строку то я поменяю а терминал об этом не узнает или он потом проверяет новую длину строки и модифицирует уже len исходя из этого?
 
Категорически нельзя трогать или изменять поле MqlStr.len - оно только для внутреннего использования виртуальной среды MQL4.
Используйте стринг как С строку, у которой концом является ноль.
 
Renat писал (а):
Категорически нельзя трогать или изменять поле MqlStr.len - оно только для внутреннего использования виртуальной среды MQL4.
Используйте стринг как С строку, у которой концом является ноль.
Renat, не могли бы вы немного осветить процедуру работы со строками при передачи строк наружу?
Как показала практика работы с дебаггером, в dll передается не ссылка на структуру (типа TMT4String) а просто pchar (т.е. только указатель на сами данные), а я уже вижу не первый раз, когда народ воспринимает этот указатель как поинтер именно на TMT4String, и начинает модифицировать поля len, и т.п.
Кто тут все таки прав?
Имхо, это будет полезно, т.к. вопросов по форуму немало, а ответов по делу почти нет.

p.s. Renat, а кто вам делал "навеску" на terminal.exe - это ваши сотрудники, или сторонний заказ?
Автору адназначно респект ;), ибо сделано весьма оригинально - вроде в наше время уже ниче нового придумать нельзя, но тем не менее, даже такие вещи как ida5.0 толком файло загрузить не могут.
Я бы вам все таки посоветовал не заморачиваться с защитой, т. к. лично у меня ушло минут 5 на выяснение причин (почему файло не грузится), и все закончилось правкой поля NumberOfRvaAndSizes (на 0x10) в OptionalHeader прям в .exe, после чего все заработало :), но автору еще раз - респект :)
Эффекта - почти что ноль (все равно сломают), а проблемы с отладкой dll создает конкретно (особенно тем, кто не знает что такое NumberOfRvaAndSizes), а отлаживать dll как тож надо...
 
Renat:
Категорически нельзя трогать или изменять поле MqlStr.len - оно только для внутреннего использования виртуальной среды MQL4.
Используйте стринг как С строку, у которой концом является ноль.
То етсь терминал уже сам впоследствии узнает что строка поменялась и сам уже модифицирует len? Главно чтобы он потом не упал используя старое значение len
 
Demax:
Renat:
Категорически нельзя трогать или изменять поле MqlStr.len - оно только для внутреннего использования виртуальной среды MQL4.
Используйте стринг как С строку, у которой концом является ноль.
Renat, не могли бы вы немного осветить процедуру работы со строками при передачи строк наружу?
Как показала практика работы с дебаггером, в dll передается не ссылка на структуру (типа TMT4String) а просто pchar (т.е. только указатель на сами данные), а я уже вижу не первый раз, когда народ воспринимает этот указатель как поинтер именно на TMT4String, и начинает модифицировать поля len, и т.п.
Кто тут все таки прав?
Имхо, это будет полезно, т.к. вопросов по форуму немало, а ответов по делу почти нет.

p.s. Renat, а кто вам делал "навеску" на terminal.exe - это ваши сотрудники, или сторонний заказ?
Автору адназначно респект ;), ибо сделано весьма оригинально - вроде в наше время уже ниче нового придумать нельзя, но тем не менее, даже такие вещи как ida5.0 толком файло загрузить не могут.
Я бы вам все таки посоветовал не заморачиваться с защитой, т. к. лично у меня ушло минут 5 на выяснение причин (почему файло не грузится), и все закончилось правкой поля NumberOfRvaAndSizes (на 0x10) в OptionalHeader прям в .exe, после чего все заработало :), но автору еще раз - респект :)
Эффекта - почти что ноль (все равно сломают), а проблемы с отладкой dll создает конкретно (особенно тем, кто не знает что такое NumberOfRvaAndSizes), а отлаживать dll как тож надо...
Как я заметил если в эксперете строка передаётся во так
func(string str);
то в Dll она будет как
func(char* str);
то есть без поля int len перед строкой.

Однако если передаём массив ссылок на строки в эксперте
func(string& strings[]) {
}
то dll будет получать указатель на массив строк типа
MqlStr {
int len;
char* string;
};
func(MqlStr* pStrings) {
}


А насчёт отладки длл. У меня получалось нормально. Правда одна проблема иногда длл не освобождалась терминалом даже если удалить эксперта с чарта (он один был).
Думаю теперь сделать так что эксперт вызывает функции init и deinit из промежуточной длл которая уже принудительно делает LoadLibrary и FreeLibrary для другой длл с нужным кодом. Мне кажется что в MQ был сделал упор на язык mql4 а работа с длл добавилась как дополнительная фича, чтобы было без хорошего продумывания и тестирования.
Но если метаквотс усовершенствует механизм работы с длл то это улучшило бы продукт значительно. Можно было бы позволить вызывать функции входящих в состав MQL4 прямо из Dll плугинов. И разрешить это только при запущенном терминале чтобы люди не делали свои терминалы а просто разрабатывали plugins к MT4.
 
elritmo:
Renat:
Категорически нельзя трогать или изменять поле MqlStr.len - оно только для внутреннего использования виртуальной среды MQL4.
Используйте стринг как С строку, у которой концом является ноль.
То етсь терминал уже сам впоследствии узнает что строка поменялась и сам уже модифицирует len? Главно чтобы он потом не упал используя старое значение len
Поле len используется нами в смысле "максимальный размер буфера". Но с оговоркой, если поле len=0, то это константная статическая строка, которую трогать категорически не реомендуется. В любом случае из DLL менять поле len нельзя, а можно только читать.

Как Вы верно заметили, при прямой передаче строки в DLL, идет прямая ссылка вида char*, а при передаче массива строк выдается MqlStr*.

Вообще-то работать с DLL из MQL4 легко, так как мы изначально делали такую интеграцию. Есть конечно особенности работы со строками, но они из-за того, что мы максимально ускорили работу с ними, введя специальный контролируемый пул строк (по сравнению с new/delete мы ускорились в десяток раз).
 
Demax:
Эффекта - почти что ноль (все равно сломают), а проблемы с отладкой dll создает конкретно (особенно тем, кто не знает что такое NumberOfRvaAndSizes), а отлаживать dll как тож надо...
В 201 билде защиту упростим и можно будет штатным образом отлаживать DLL.
 
Renat:
elritmo:
Renat:
Категорически нельзя трогать или изменять поле MqlStr.len - оно только для внутреннего использования виртуальной среды MQL4.
Используйте стринг как С строку, у которой концом является ноль.
То етсь терминал уже сам впоследствии узнает что строка поменялась и сам уже модифицирует len? Главно чтобы он потом не упал используя старое значение len
Поле len используется нами в смысле "максимальный размер буфера". Но с оговоркой, если поле len=0, то это константная статическая строка, которую трогать категорически не реомендуется. В любом случае из DLL менять поле len нельзя, а можно только читать.

Как Вы верно заметили, при прямой передаче строки в DLL, идет прямая ссылка вида char*, а при передаче массива строк выдается MqlStr*.

Вообще-то работать с DLL из MQL4 легко, так как мы изначально делали такую интеграцию. Есть конечно особенности работы со строками, но они из-за того, что мы максимально ускорили работу с ними, введя специальный контролируемый пул строк (по сравнению с new/delete мы ускорились в десяток раз).
Спасибо за информацию про строки. Этот вопрос думаю решён. Буду задавать максимальную длину строк и модифицировать поле string только или есть вариант как предложил один господин посредством передачи массива указателей на int и последующим преобразованием его в строки и ноборот. Это может сэкономить память если строк будет много. Не надо резервировать сразу максимальный размер. Кстати когда я создаю строки в эксперте я же не говорю ему максимальный размер строки. Как же вы записываете тогда в поле len максимальную длину строки? И если вы выбираете размер буфера максимальный то и размер строки тоже видимо ограничивается максимальным значением строки. Надо глянуть в доке по MQL4. Но если такого ограничения нет то максимальный размер видимо указывается как MAX_INT
А насчёт интеграции с длл она реализована но вот есть ограничения на передачу структур данных между экспертом и DLL и вообще вызов функций из длл происходит медленнее чем если бы я в длл переписывал функции start init и прочие а терминал бы вызывал их уже из моего длл плугина.
Причина обращения: