Помогите с указателями на функцию
- Войдите на сайт для отправки комментариев
Есть функция чтения значения аналогового пина
int solid_read(int pin)
{
int val = analogRead(pin);// считываем значение
val = map(val, 0 , 1023, 100, 0);
return val; // выводим полученное значение
}
Есть функция меню
void up_down_eeprom_var( int var )
{
int x =0;
lcd.clear(); //очищаем экран
delay(del);
while(1)
{
x++;
if (x>interval){break;}
lcd.print(" now=");
lcd.print(var);
}}
Как правильно передеть функции void up_down_eeprom_var(int var ) указатель на функцию int solid_read(int pin) (параметр int var)? чтобы внутри функции up_down.. читалось значение функции solid_read при каждой итерации цикла while?
Что делал:
создал указатель на функцию :
int (*pi)(int);
void setup() {
pi = &solid_read;
Далее вызываю функцию void up_down_eeprom_var(pi(0))
и в lcd.print(var); выводит статичное значение, которое не меняется... ) Если подставить вместо lcd.print(var); -> lcd.print(pi(0)); то всё ок,функция читается, но так мне не нужно т.к. есть много других функций которые мне надо туда передавать.... , ; второй вечер сижу голову ломаю...как полноценно читать функцию solid_read(int pin) внутри функции void up_down_eeprom_var( int var )? посредством указателей?=) надеюсь объяснил понятно =)
Как-то так
void up_down_eeprom_var(int func()) { value = func(0); } up_down_eeprom_var(solid_read);не работает...
Из текущего проекта
typedef void (*FunOneWireDev)(OneWireDevID id); //Поиск и перебор устройств boolean ScanOneWire(FunOneWireDev pCallBack) { OneWireDevID OneWire; boolean res=false; if(Termometr.OneWireBeginFindDevice()) { res=true; if(Termometr.OneWireFindNextDevice(OneWire)) pCallBack(OneWire); } return res; } void TestOneWireDev(OneWireDevID id) { static byte No; Serial.print("dev"); Serial.print(No); Serial.print(":"); for(byte i=0;i<sizeof(OneWireDevID);i++) { Serial.print(id[i],HEX);Serial.print(" "); } No++; } ..... if(ScanOneWire(TestOneWireDev)) Serial.println("end"); else Serial.println("no");не могли бы вы пояснить что-куда-откуда, а то не понятно..
не могли бы вы пояснить что-куда-откуда, а то не понятно..
Так написано ж - ScanOneWire(TestOneWireDev)! Соответственно в ScanOneWire передаем указатель на TestOneWireDev и оно там его того.
Спрашуйте конкретней, что не понятно.
dachnik, тебе вроде нужно вместе с указателем на функцию еще и её параметр передать... сделай так:
int up_down_eeprom_var(int func(int), int param) { return func(param); } value = up_down_eeprom_var(solid_read, 0);// создаём тип указателя на функцию, возвращающую int, и принимающую параметром int typedef int (*RetIntReceiveIntFunc)(int param); // теперь в нашей функции eeprom_что-то_там делаем параметр с типом: void eeppom_read_var(RetIntReceiveIntFunc func) { // теперь вызываем функцию по переданному указателю, передавая ей нужное значение // и получая результат Serial.println("Call passed func with param=100"); int res = func(100); Serial.print("Result are: "); Serial.println(res); } // теперь пишем нашу функцию, которая будет вызываться int testFunc(int val) { Serial.print("Passed: "); Serial.println(val); return val*2; } // тестируем void setup() { Serial.begin(9600); eeppom_read_var(testFunc); // пробуем, чего напечаталось. }может надо просто вызвать функцию где надо?
void up_down_eeprom_var( int var, int pin ) { int x =0; lcd.clear(); //очищаем экран delay(del); while(1) { int readpin = solid_read(pin); //вызов x++; if (x>interval){break;} lcd.print(" now="); lcd.print(var); }}хотя с твоими кусками кода не понятно какого хрена ты вообще хочешь сделать
ни вызова функций нихрена нет, зачем тебе вообще указатели?
2 функции нельзя никуда передавать!!! функция это алгоритм действия над чемто (данными) как? да и зачем? их кудато передавать!
Задачу нормально сформулируй! и код нормальный дай!!
хотя готов догадаться что должно быть так
void up_down_eeprom_var( int var) { int x =0; lcd.clear(); //очищаем экран delay(del); while(1) { int readpin = solid_read(pin); //вызов x++; if (x>interval){break;} lcd.print(" now="); lcd.print(solid_read(var)); //вывести значение пина var }}Всем спасибо за советы, но выручила книжка по плюсам
void up_down_eeprom_var(byte eeprom_val, String label, int (*var)()); //объявляем функцию которая имеет указатель void menu() функция выбора меню { int (*p)(); //создаем указатель на функцию p=temp_in; //присваиваем адрес функции temp_in() указателю *p up_down_eeprom_var(eeprom_solid_var_1, soil_eeprom_var_1_str, p); //вызываем функцию с указателем *p } void up_down_eeprom_var(byte eeprom_val, String label, int (*var)()) { int x =0; lcd.clear(); //очищаем экран delay(del); while(1) { //бесконечный цикл x++; if (x>interval){break;} button_read(); lcd.setCursor(0,0); lcd.print(label); lcd.setCursor(0,1); lcd.print("set ="); lcd.print(EEPROM.read(eeprom_val)); lcd.print(" now="); lcd.print(var()); //хали хоп! и функция temp_in() обрабатывается внутри функции void up_down_eeprom_var с использованием указателя на функцию! } int temp_in() { sensors.requestTemperatures(); // Send the command to get temperatures int t = dht.readTemperature(); return t; }Единственное, пока научился передавать функцию, не имеющую параметров, а как скажем передать функцию, которая была описана в первом посте:
int solid_read(int pin) { int val = analogRead(pin);// считываем значение val = map(val, 0 , 1023, 100, 0); return val; // выводим полученное значение }?
Сообщение #6
temp_in()прямо внутри
? цель твоих действий?
Цель такова что эта функция up_down_eeprom_var служит для вызова разных настроек меню и является универсальной функцией для настройки энергонезависимой памяти контролера. Датчиков много функция одна. Экономия места и простота добавления новых устройств.
Сообщение #6
Еще один лишний параметр. Можно вместе с указателем передавать...главное правильно синтаксис написать. А с этим проблема компилятор ругается
типа примитивный вариант обработчика событий ))
только вот я не не пойму о каких аргументах ты толкуешь, откуда этой функции которая всё вызывает должна знать аргументы, даже чисто логически не может знать, она и должна аргументы раздавать или запрашивать их откудато
Сообщение #6
Еще один лишний параметр. Можно вместе с указателем передавать...главное правильно синтаксис написать. А с этим проблема компилятор ругается
И? Исходник и копия ошибки. Если нет, то разбирайся сам, не вопрос.
Единственное, пока научился передавать функцию, не имеющую параметров, а как скажем передать функцию, которая была описана в первом посте:
Чем не устроило сообщение номер 7? Чукча не читатель?
не компилится...
Вот спецом взял и скомпилировал:
// создаём тип указателя на функцию, возвращающую int, и принимающую параметром int typedef int (*RetIntReceiveIntFunc)(int param); // теперь в нашей функции eeprom_что-то_там делаем параметр с типом: void eeppom_read_var(RetIntReceiveIntFunc func) { // теперь вызываем функцию по переданному указателю, передавая ей нужное значение // и получая результат Serial.println("Call passed func with param=100"); int res = func(100); Serial.print("Result are: "); Serial.println(res); } // теперь пишем нашу функцию, которая будет вызываться int testFunc(int val) { Serial.print("Passed: "); Serial.println(val); return val*2; } // тестируем void setup() { Serial.begin(57600); eeppom_read_var(testFunc); // пробуем, чего напечаталось. } void loop() { // put your main code here, to run repeatedly: }Запустил, как ожидалось, в мониторе порта появилось:
Не компилируется, мдя... Конечно, если не думать и дописать в строчке
Что-то типа
То компилироваться перестанет - с чего бы это, Карл?
sketch_mar16a.ino:3:22: error: variable or field 'eeppom_read_var' declared void sketch_mar16a.ino:3:22: error: 'RetIntReceiveIntFunc' was not declared in this scope sketch_mar16a.ino: In function 'void setup()': sketch_mar16a.ino:28:30: error: invalid conversion from 'int' to 'RetIntReceiveIntFunc {aka int (*)(int)}' [-fpermissive] sketch_mar16a.ino:6:6: error: initializing argument 1 of 'void eeppom_read_var(RetIntReceiveIntFunc)' [-fpermissive] Ошибка компиляции.всё равно
sketch_mar16a.ino:3:22: error: variable or field 'eeppom_read_var' declared void sketch_mar16a.ino:3:22: error: 'RetIntReceiveIntFunc' was not declared in this scope sketch_mar16a.ino: In function 'void setup()': sketch_mar16a.ino:28:30: error: invalid conversion from 'int' to 'RetIntReceiveIntFunc {aka int (*)(int)}' [-fpermissive] sketch_mar16a.ino:6:6: error: initializing argument 1 of 'void eeppom_read_var(RetIntReceiveIntFunc)' [-fpermissive] Ошибка компиляции.всё равно
Блин. Это ж пример! Понимаете? ПРИ-МЕ-Р! Вы бездумно его вставили в свой код и хотите, чтобы заработало? Я не переписывал имена ваших функций, например. Ещё раз говорю: скетч компилируется. Что и куда вы вставили - вопрос: вы же не приводите ни строчки кода, который вы изменили!
Вижу лишь, что вы неправильно применяете пример, судя по
nvalid conversion from 'int' to 'RetIntReceiveIntFunc {aka int (*)(int)}Если действительно хотите разобраться - либо давайте сюда кусок изменённого кода, который не компилируется, либо - читайте учебники по С++, в частности, про указатели, в частности - про указатели на функции.
Иначе всё это - разговор глухого с немым - понадёргают кусков кода, а потом - не компилируется. Вы хоть пробовали сделать так, как я писал: создать новый скетч, вставить туда мой код и убедиться в мониторе порта, что внутри eeprom_read_var вызывается функция, переданная по указателю на неё в eeprom_read_var? Проще уже некуда написать - посмотрите, что выводится в Serial.