CallBack Function с параметром
- Войдите на сайт для отправки комментариев
Ср, 23/05/2018 - 19:50
Доброго времени суток. Задачка следующая.
Есть библиотека (могу привести полный код). Кусок меня интересующий ниже.
Суть такова, что создается объект типа AlarmClass, с параметрами: время и функция обратного вызова, но проблема в том, что она (эта функция) идет без параметров, а мне нужно передать в нее параметр.
Сейчас вызов идет вот так
Alarm.timerOnce(10, OnceOnly); void OnceOnly() { Serial.println("Test"); }
А хочется вот так
Alarm.timerOnce(10, OnceOnly(123)); void OnceOnly(data) { Serial.println(data); }
Я полез в библиотеку и поменял typedef void (*OnTick_t)(byte); // alarm callback function typedef
Но получаю ошибку "invalid use of void expression"
Подскажите, как правильно оформить передачу параметра.
Код библы
typedef void (*OnTick_t)(); // alarm callback function typedef //typedef void (*OnTick_t)(byte); // alarm callback function typedef // class defining an alarm instance, only used by dtAlarmsClass class AlarmClass { public: AlarmClass(); OnTick_t onTickHandler; void updateNextTrigger(); time_t value; time_t nextTrigger; AlarmMode_t Mode; }; // class containing the collection of alarms class TimeAlarmsClass { private: AlarmClass Alarm[dtNBR_ALARMS]; void serviceAlarms(); uint8_t isServicing; uint8_t servicedAlarmId; // the alarm currently being serviced AlarmID_t create(time_t value, OnTick_t onTickHandler, uint8_t isOneShot, dtAlarmPeriod_t alarmType); public: TimeAlarmsClass(); // functions to create alarms and timers // trigger once at the given time in the future AlarmID_t triggerOnce(time_t value, OnTick_t onTickHandler) { if (value <= 0) return dtINVALID_ALARM_ID; return create(value, onTickHandler, true, dtExplicitAlarm); } // trigger once at given time of day AlarmID_t alarmOnce(time_t value, OnTick_t onTickHandler) { if (value <= 0 || value > SECS_PER_DAY) return dtINVALID_ALARM_ID; return create(value, onTickHandler, true, dtDailyAlarm); } AlarmID_t alarmOnce(const int H, const int M, const int S, OnTick_t onTickHandler) { return alarmOnce(AlarmHMS(H,M,S), onTickHandler); }
Перечитывал, я там ошибся. Хочется вот так
Смотри, какое дело: то, что ты делаешь (Alarm.timerOnce(10, OnceOnly(123));) - это ВЫЗОВ функции OnceOnly с параметром 123.
Если тебе надо, чтобы вызывающая сторона умела передавать какой-либо дополнительный параметр, то:
delay там чисто для прикола, я просто показал принцип, как сделать.
Круто, спасибо!!!
Получается придется конкретно библу переколбасить, протащить параметр в конструктор... и как-то поменять вызов.
Буду пробывать
Как вариант просто сделать добавку, что бы и так и так.
Спасибо большое за пример! Именно так и сделаю.
Только я не совсем понял, не надо разве в секцию private задать PHandlerA handler;
Спасибо большое за пример! Именно так и сделаю.
Только я не совсем понял, не надо разве в секцию private задать PHandlerA handler;
Надо, квон просто забыл ;)
А зачем много тратить памяти. Я просто сделал приведение к беспараметному виду. Если надо запустить снова, то приведите к типу с параметром и запустите.
Чего-то у меня не сростается.
Завел новый тип с параметром OnTickByte_t
В описании класса AlarmClass ввел переменные OnTickByte_t onTickByteHandler; byte param;
В описании класс TimeAlarmsClass ввел новый конструктор AlarmID_t createbyte(time_t value, OnTickByte_t onTickByteHandler, uint8_t isOneShot, dtAlarmPeriod_t alarmType, byte param);
В конструкторе сохраняю значение Alarm[id].param = param;
И в процедуре void TimeAlarmsClass::serviceAlarms() ввел новый вызов.
Все нашел!!!!
У меня не стартовал таймер, там тоже проверка хэндла была. Добавил свой и все заработало.
Огромное всем спасибо!!!!
Когда у тебя переменная - указатель на функцию, разыменовывать через звездочку ее не надо, gcc и так пропускает, а читабельность получше маленько. Хотя, чоэтоя, где С, а где читабельность...
Вот так тоже прокатит
098
if
( !TickByteHandler ) TickByteHandler(param);
Когда у тебя переменная - указатель на функцию, разыменовывать через звездочку ее не надо, gcc и так пропускает, а читабельность получше маленько. Хотя, чоэтоя, где С, а где читабельность...
Вот так тоже прокатит
098
if
( !TickByteHandler ) TickByteHandler(param);
Деда, убери !, а то у тоби NULL разыменуется :)
Да. ! лишний. Ну это я не иначе, с пахмелью. Простите.
DIYMan, спасибо, что разглядел.
Добрый день. Ситуация у меня похожая. Arduino due, 15 кнопок. По нажатию на каждую из них выполняется однотипный код. В развернутом виде все работает, но переписывание одной и той же функции 15 раз... Прочитал ветку. Решил сделать "оптимизацию". Но при компилировании получаю ошибку в строках 31 и 40: invalid use of void expression. Что я не так делаю? И вообще возможно ли это в прерываниях?
атачить в прерывания тока статическую ф-ию и без параметров, делайте обертку. А воще подход какойто мутный. Нафига там класс? И так ли нужны прерывания на кнопки при пустом лупе.
атачить в прерывания тока статическую ф-ию и без параметров, делайте обертку. А воще подход какойто мутный. Нафига там класс? И так ли нужны прерывания на кнопки при пустом лупе.
Луп там не пустой. Я этот пример написал отдельно и облегченно. В кратце - станок, 4 шаговых движка, 5 пневмоцилиндров порядка 12 датчиков и тому подобное. от delay и прочих тяжелых вещей я отказался. зачем например в лупе перечитывать состояние всей периферии, если есть возможность точечно получить инфу о событии. плюс с защитой от дребезга. Благо Due это позволяет. Как я и писал, код рабочий, но очень длинный. вот и пытаюсь в виду (стандартаная фраза на этом форуме) не совсем сильных познаниях в с++, научиться и сделать некоторую оптимизацию кода. Статическая функция и без параметров в обертке это примерно как? Что то типа глобальной переменной, обработка которой уже внутри стандартной Callback функции? Типа вот так:
похоже. Но работать не будет, при вызове прерывания id откуда возмется?
Если луп не пустой и прокручивается довольно быстро, не хуже сотни мсек то чтото вроде такого
избавит от гемора и сильно сократит код.
похоже. Если луп не пустой и прокручивается довольно быстро, не хуже сотни мсек то чтото вроде такого
избавит от гемора и сильно сократит код.
Это я пробовал, но тогда получаю неравномерность работы ШД. (использую AccelStepper) и если в датчиках ПЦ - два на цилиндр нет дребезга, то на кнопках дребезг есть, несмотря на шунтирование кнопок кондерами
id - ну да...
при атаче - понятно, а при вызове прерывания?
Время отработки приведеного кода порядка десятков мксек, он быстрый, он не может повлиять на ШД. Если надо быстрей - digitalRead меняем на прямую работу с регистром, int i на byte i, разворачиваем цикл, можна до нескольких мксек дооптимизироапть.
4 ШД, требуемая частота импульсов для каждого разная один от 2400/сек до 4800/сек период соответственно от 415 мкСек до 208 мкСек. ну и так далее. Приведенный код да, время не большое. А дребезг?
А че дребезг? С ним хоть через прерывание, хоть напрямую - ситуация одинаковая, даже через прерывание хуже т.к. каждый фронт дребезга будет вызывать обработчик а это затраты времени в пустую. А алгоритм подавления дребезга, если он вобще есть и если вобще нужен - одинаковый.
4 ШД, требуемая частота импульсов для каждого разная один от 2400/сек до 4800/сек период соответственно от 415 мкСек до 208 мкСек. ну и так далее. Приведенный код да, время не большое. А дребезг?
Ага. Станцию подавления дребезга монтировать, если ума нет код писать.