Вы упускаете торговые возможности:
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Регистрация
Вход
Вы принимаете политику сайта и условия использования
Если у вас нет учетной записи, зарегистрируйтесь
https://www.mql5.com/ru/forum/148850
Вот тебе и раз. Чувствую себя так, как будто из какой-нибудь пещеры вылез :) Такие дела творятся, а я про них ничего не знаю :)
Надо будет перебираться на новый язык потихоньку.
Пользуйтесь кнопкой SRC, чтобы код вставлять.
Ну, в общем-то, код показать всегда лучше, хотя он и кривоват :) Я решил пробовать без указателей (через хранение их в статических переменных), но проблемный код всё же приведу.
Сначала объяснение, как оно работает. Используется Qt 4. В DLL объявлены экспортируемые функции - те, которые будут вызываться из MQL4. Также описан класс, который отвечает за работу с БД. Назначение класса простое - по запросу от робота открывает соединение с БД и сохраняет его во внутренней переменной, а функция возвращает указатель на созданный объект этого класса роботу. Потом другая функция принимает от робота этот указатель и данные, которые роботу надо в базу записать. Все данные передаются параметрами фу6кций с простыми типами - int, double, string, больше ничего. При завершении работы вызывается функция деинициализации, которая вызывает в классе функцию закрытия соединения и затем освобождает объект класса. Чтение данных из БД внутри робота не производится (планируется в будущих версиях по той же схеме). Вот с передачей указателя возникла проблема. Вернее, я думаю, что проблема с передачей указателя. Но на самом деле она может быть и в чем-то другом.
Функция инициализации - создаёт объект класса MqlDll (который работает с БД), открывает соединение через вызов функции класса и возвращает ссылку на класс, преобразованную в int, роботу:
Описание этой функции в роботе на MQL4:Функция деинициализации (закрытие соединения выполняется в деструкторе класса): Описание этой функции в роботе на MQL4. Полученный от функции инициализации указатель робот передаёт в функцию, как int: Ну и для примера одна из функций, работающих с указателем. Служит для получения от класса описания последней ошибки, произошедшей при работе с БД: Описание на MQL4: Вот примерно так оно всё и работало.
1. Между запусками эксперта требуется держать данные в классе MqlDll? Эксперт, может даже несколько экспертов, могут быть загружены/выгружены несколько раз и, если все потоки завершились, то библиотека выгрузится. Данные класса будут потеряны.
2. Если класс объявлен глобально и ссылается на другие глобальные объекты, если они существуют (?), то синглетон необходим. Иначе, возможны непрогнозируемые разнообразные ошибки. Причём, на каждый раз новые :-)
3. Пользуетесь всеми параметрами функции инициализации? Т.е. у Вас несколько вызовов с разными значениями?
4. По поводу коммутации. Подойдёт ассоциативный контейнер (std::map). Складываейте в него пары идентификатор-указатель. Снаружи оперируйте идентификатором. Андрей выше написал, как делать.
Ну думай что ты меня макнул ) если тебе так легче .
Сначала подумай сто раз, прежде, чем что-то сказать или написать.
А то, хотел ближнего макнуть, да сам обмочился :-)
Это как? фонит что ли? ) ну покажи свой православный для тех же задач )
Сильно удивлён, что ТЕБЕ буду ЭТО объяснять. Это же базовые знания!
1. Так синхронизацию никто не делает. Критическая секция должна быть в классе-обёртке.
2. К ней нужен шаблон класса-замка. Если у тебя один класс объекта синхронизации, можно без шаблона. У меня их 4 для всех случаев жизни.
3. Сам синглетон это отдельная сущность. Должен быть шаблоном класса. Любой свой класс можно сделать синглетоном путём наследования от своего класса.
4. Класс критической секции для синглетона должен быть с глобальным инстансом. Одним на все твои синглетоны.
5. Ну, и для законченных перфекционистов :-)) Нужна функция чистки памяти от глобального инстанса класса критической секции перед завершением приложения или библиотеки. Собственно, это один из методов этого глобального инстанса.
6. Надеюсь, не надо говорить, что все указатели в синглетонах должны быть умными?
Это просто. Один раз надо сделать. Больше никогда никаких ошибок при исполнении не будет.
Потом делаю макрос так:
Обращение к методам:
Проще некуда.Вот вариант с наследованием.
Пользуйтесь кнопкой SRC, чтобы код вставлять.
1. Между запусками эксперта требуется держать данные в классе MqlDll? Эксперт, может даже несколько экспертов, могут быть загружены/выгружены несколько раз и, если все потоки завершились, то библиотека выгрузится. Данные класса будут потеряны.
2. Если класс объявлен глобально и ссылается на другие глобальные объекты, если они существуют (?), то синглетон необходим. Иначе, возможны непрогнозируемые разнообразные ошибки. Причём, на каждый раз новые :-)
3. Пользуетесь всеми параметрами функции инициализации? Т.е. у Вас несколько вызовов с разными значениями?
4. По поводу коммутации. Подойдёт ассоциативный контейнер (std::map). Складываейте в него пары идентификатор-указатель. Снаружи оперируйте идентификатором. Андрей выше написал, как делать.
Логику работы кнопки SRC я не особо понял. Нажимаю - у меня весь набранный текст сообщения полностью пропадает, появляется новое поле ввода. Отжимаю - опять вижу своё сообщение. Поэтому сделал предыдущее сообщение таким..
Теперь по пунктам.
1. Между запусками эксперта ничего в самом классе не сохраняется. Запустился эксперт - для него создался объект класса, инициализировался, создал подключение к БД и держит его. Все данные - только на текущий сеанс работы, типа строки с последней ошибкой. Все данные, которые надо сохранять после запуска, хранятся в БД (для чего и нужно подключение). Данные, которые надо сохранять между запусками одного робота - хранятся в глобальных переменных. Так что потеряно ничего не будет.
2. С синглетонами не работал до этого. Класс MqlDll объявлен глобально. Кроме него, планируется сделать коасс со статическим контейнером (std::map, или, вернее, "QMap<Key, T>") для хранения указателей. До этого я думал просто сделать статический класс и в нём блокировку для многопоточно-безопасного обращения к контейнеру. Надо будет погуглить синглетон и посмотреть, что это такое, зачем он нужен и как его приделать к своему классу.
3. Функция инициализации одна. Параметры, конечно, используются все. Это обычные параметры подключения к БД - хост, порт, логин, пароль, название БД. Их надо передавать все каждый раз. Кроме этого ещё название подключения - оно нужно для классов Qt.
4. Насчёт контейнера с парами "идентификатор-указатель" - это да, отличное решение сложной проблемы, которое я как раз и планирую приделать. Я использую Qt. В нём можно приделать и std::map, но там были какие-то сложности с этим, и потому в Qt куча своих классов-контейнеров. В частности, есть "QMap<Key, T>".
0. Логику работы кнопки SRC я не особо понял. Нажимаю - у меня весь набранный текст сообщения полностью пропадает, появляется новое поле ввода. Отжимаю - опять вижу своё сообщение. Поэтому сделал предыдущее сообщение таким..
Теперь по пунктам.
1. Между запусками эксперта ничего в самом классе не сохраняется. Запустился эксперт - для него создался объект класса, инициализировался, создал подключение к БД и держит его. Все данные - только на текущий сеанс работы, типа строки с последней ошибкой. Все данные, которые надо сохранять после запуска, хранятся в БД (для чего и нужно подключение). Данные, которые надо сохранять между запусками одного робота - хранятся в глобальных переменных. Так что потеряно ничего не будет.
2. С синглетонами не работал до этого. Класс MqlDll объявлен глобально. Кроме него, планируется сделать класс со статическим контейнером (std::map, или, вернее, "QMap<Key, T>") для хранения указателей. До этого я думал просто сделать статический класс и в нём блокировку для многопоточно-безопасного обращения к контейнеру. Надо будет погуглить синглетон и посмотреть, что это такое, зачем он нужен и как его приделать к своему классу.
3. Функция инициализации одна. Параметры, конечно, используются все. Это обычные параметры подключения к БД - хост, порт, логин, пароль, название БД. Их надо передавать все каждый раз. Кроме этого ещё название подключения - оно нужно для классов Qt.
4. Насчёт контейнера с парами "идентификатор-указатель" - это да, отличное решение сложной проблемы, которое я как раз и планирую приделать. Я использую Qt. В нём можно приделать и std::map, но там были какие-то сложности с этим, и потому в Qt куча своих классов-контейнеров. В частности, есть "QMap<Key, T>".
0. :-)) Представляете, в это поле можно даже что-то написать?!
2. Синглетон нужен для своевременной инициализации глобальных объектов, которые ссылаются друг на друга. Чтобы не было такого, когда инициализируется один класс и при этом использует другой ещё неинициализированный класс. Порядок инициализации от каждого запуска будет разный. Соответственно каждый раз новые ошибки. Иногда без ошибок.
Без контейнера не обойтись. Синхронизация при обращении к нему обязательна. Кстати, в этом случае можно работать даже с 64-разрядной базой. Ведь, указатели можно в контейнере хранить уже какие угодно.
4. Да, это тот же std::map. Аналог.
0. :-)) Представляете, в это поле можно даже что-то написать?!
2. Синглетон нужен для своевременной инициализации глобальных объектов, которые ссылаются друг на друга. Чтобы не было такого, когда инициализируется один класс и при этом использует другой ещё неинициализированный класс. Порядок инициализации от каждого запуска будет разный. Соответственно каждый раз новые ошибки. Иногда без ошибок.
Без контейнера не обойтись. Синхронизация при обращении к нему обязательна. Кстати, в этом случае можно работать даже с 64-разрядной базой. Ведь, указатели можно в контейнере хранить уже какие угодно.
4. Да, это тот же std::map. Аналог.
Спасибо за консультации :)
Я планирую сделать так. Класс MqlDll, обеспечивающий работу с БД, оставить без изменений. В дополнение к нему сделать статический класс, который будет обеспечивать хранение указателей в контейнере, получение указателя по идентификатору, потокобезопасное создание класса и помещение его в контейнер с получением идентификатора и т.п.
Насколько я понимаю, раз статический класс будет один - то порядок инициализации особого значения не имеет, а значит, можно без синглетона?
Спасибо за консультации :)
Я планирую сделать так. Класс MqlDll, обеспечивающий работу с БД, оставить без изменений. В дополнение к нему сделать статический класс, который будет обеспечивать хранение указателей в контейнере, получение указателя по идентификатору, потокобезопасное создание класса и помещение его в контейнер с получением идентификатора и т.п.
Насколько я понимаю, раз статический класс будет один - то порядок инициализации особого значения не имеет, а значит, можно без синглетона?