Добрый день! Использую библиотеку liquidmenu для создания меню, пытаюсь привязать к линиям функцию с аргументом Код (C++): void Group1_ON(int on) { digitalWrite(SWG_1, HIGH); digitalWrite(on, HIGH); //SWR digitalWrite(SUO, HIGH); delay(100); digitalWrite(SWG_1, LOW); digitalWrite(on, LOW); //SWR digitalWrite(SUO, LOW); int c = on - 0; SK[c] = {digitalRead(SK_1)}; if (SK[c] == 1) { K_STR[on] = K_STR[on] + "ON" + "\x94"; } else K_STR[on] = K_STR[on] + "ON" + "\x21"; K9.attach_function(1, Group1_ON(1)); При этом возникает ошибка:Invalid use of void exception. Как я понял, это связано с тем, что attach_function в классе liquidline не предусматривает аргумента: Код (C++): bool LiquidLine::attach_function(uint8_t number, void (*function)(void)) { print_me(reinterpret_cast<uintptr_t>(this)); if (number <= MAX_FUNCTIONS) { _function[number - 1] = function; DEBUG(F("Attached function ")); DEBUGLN(number); _focusable = true; return true; } else { DEBUG(F("Attaching function ")); DEBUG(number); DEBUGLN(F(" failed, edit LiquidMenu_config.h to allow for more functions")); return false; } } Попробовал добавить этот аргумент, но на данном этапе я уже совсем не понимаю, что происходит и действую наобум Код (C++): bool LiquidLine::attach_function_int(uint8_t number, void (*function)(int)) { Собственно вопрос, как можно это реализовать?
в этой строчке Код (C++): K9.attach_function(1, Group1_ON(1)); вы пытаетесь передать ссылку на функцию с конкретным аргументом "1" - это неверно. у ссылки на функцию нет аргументов. нужно передавать ссылку на функцию отдельно от параметров, например так Код (C++): K9.attach_function(1, 1, Group1_ON); где вторая единица в скобках - это аргумент для функции Group1_ON(int) Соответвенно и заголовок функции LiquidLine::attach_function() должно быть переписано как: Код (C++): bool LiquidLine::attach_function_int(uint8_t number, int par, void (*function)(int)) { ну и код функции соответственно
Ошибку понял, как реализовать - не понимаю. В библиотеке в классе liquidline существует только функция liquidLine::attach_function(), с одним аргументом и ссылкой на void() функцию. Я добавил в liquidline.cpp строку и полностью скопировал тело liquidLine::attach_function() в LiquidLine::attach_function_int. Код (C++): bool LiquidLine::attach_function_int(uint8_t number, int par, void (*function)(int)) { Но компилятор пишет, ошибку 'class LiquidLine' has no member named 'attach_function_int'; did you mean 'attach_function'?. Второй вопрос, как теперь сослаться на int par при объявлении функции void Group1_ON(int on). Как указать, что int on=int par?
Есть подозрение, что не правильно решаете свою задачу. Если в момент регистрации функции знаете с каким параметром её нужно вызвать, то регистрируйте функцию, которая будет работать с нужным параметром. Пример: Код (C++): void Group1_ON(int on) { digitalWrite(SWG_1, HIGH); digitalWrite(on, HIGH); //SWR digitalWrite(SUO, HIGH); delay(100); digitalWrite(SWG_1, LOW); digitalWrite(on, LOW); //SWR digitalWrite(SUO, LOW); int c = on - 0; SK[c] = {digitalRead(SK_1)}; if (SK[c] == 1) { K_STR[on] = K_STR[on] + "ON" + "\x94"; } else K_STR[on] = K_STR[on] + "ON" + "\x21"; } void Group1_ON_1() { Group1_ON(1); } K9.attach_function(1, Group1_ON_1); Если же, параметр функции меняется во время работы программы, то функция должна "уметь" получать значение параметра не через аргумент функции, а другим образом, например, через глобальную переменную. Т.е. функция без параметров читает глобальную переменную.
В данной библиотеке liquidline.h нет, описание есть в liquidmenu.h, туда добавил, ошибка ушла. Но как сослаться на int par в void Group1_ON(int *par) я не понимаю, буду рад, если подскажете. В моем случае придется зарегистрировать 20 функций(будет задействовано 20 пинов), и потом еще столько же раз выполнить attach.function.
не надо ссылаться на параметр в ссылке на функцию, передавайте их отдельно. А уже в самом методе LiquidLine::attach_function() вызывайте функцию с нужным параметром. функции достаточно одной, а вот attach вам по любому придется выполнить столько раз. сколько у вас значений параметра
В Вашем случае лучше сделать двадцать функций, которые будут вызывать функцию с определённым параметром (пример кода приводил в сообщении #4). И каждую функцию зарегистрировать через 'LiquidLine::attach_function()'. Меньше проблем соберёте на свою голову....
В функцию 'LiquidLine::attach_function()' передаётся адрес функции, а не её вызов. Поэтому ни каких параметров передать нельзя. Для этого придётся переписать некоторое количество кода библиотеки 'liquidmenu', при этом не просто добавить заголовок и реализацию нужной функции, как Вы советовали. Не уверен, что автор темы это осилит.
Ну почему же нельзя? Вызов функции с аргументом - нельзя. а отдельным параметром ссылку на функцию и другим параметром аргумент - вполне себе можно да я ему вроде все уже описал в #2, что там осиливать. Да. придется добавить в библиотеку свою функцию 'LiquidLine::attach_function_int()' - но вряд ли это так сложно
Можно, но этого мало. Нужно запомнить этот параметр (int) и при этом запомнить адрес функции. И в общем случае запомнить соотношение параметра (int) с адресом функции, в частном случае (нужно понимать в каком) достаточно запомнить параметры и адрес одной функции. Потом эти (эту) функции вызывать в нужном месте с правильным параметром. Ну добавите в класс метод 'attach_function_int', который будет регистрировать функцию с параметром, а вызывать эту зарегистрированную функцию в нужный момент с этим параметром кто будет? Впрочем, повторяюсь..... Судя по вопросам, автор не осилит.....
Именно так, задачу вы поняли верно. И в этом вы правы, что нужно сделать, я понял. А вот как это сделать - для меня загадка, придется писать отдельную функцию на каждый пункт меню, как я в принципе и сделал это изначально
Если используете язык C++, то можно немного упростить себе задачу, применив шаблоны: Код (C++): void Group1_ON(int on) { digitalWrite(SWG_1, HIGH); digitalWrite(on, HIGH); //SWR digitalWrite(SUO, HIGH); delay(100); digitalWrite(SWG_1, LOW); digitalWrite(on, LOW); //SWR digitalWrite(SUO, LOW); int c = on - 0; SK[c] = {digitalRead(SK_1)}; if (SK[c] == 1) { K_STR[on] = K_STR[on] + "ON" + "\x94"; } else K_STR[on] = K_STR[on] + "ON" + "\x21"; } // Декларируем шаблон для всех функций // компилятор сам сделает нужное количество функций с заданными параметрами template<int I> void Group1_ON_i() { Group1_ON(I); } // далее в коде регистрируем функции // в угловых скобках желаемый параметр // компилятор сделает функцию Group1_ON_i<1>, // в которой будет вызываться функция Group1_ON(1); K1.attach_function(1, Group1_ON_i<1>); // компилятор сделает функцию Group1_ON_i<9>, // в которой будет вызываться функция Group1_ON(9); K9.attach_function(1, Group1_ON_i<9>); Это чтобы в ручную не плодить декларации нужных функций -- пусть компилятор за нас поработает.