Помогите с кодом
- Войдите на сайт для отправки комментариев
Пт, 28/08/2015 - 19:33
народ, подскажите пожалуйста новичку как правильно вызвать функцию, параметром для которой являются несколько структур
моя подпрограмма
bool Rcv (byte node, uint8_t type) {
bool ok = false;
network.update();
RF24NetworkHeader header(node, type);
if (type == TYPE_PING) ok = network.read(header, p, sizeof(p));
else if (type == TYPE_METEO1) ok = network.read(header, s, sizeof(s));
else if (type == TYPE_TABLO1) ok = network.read(header, t, sizeof(t));
else if (type == TYPE_TIME1) ok = network.read(header, c, sizeof(c));
Serial.print("Read from ");
Serial.print(node, HEX);
Serial.print(" type ");
Serial.print(type, HEX);
if (ok)Serial.println(" OK");
else Serial.println(" Fail");
return ok;
}
здесь p, s, t, c - указатели на 4 различные структуры.
как избавиться от перечислителя, подставив структуру как параметр?
Не до конца понял, чего Вы хотите.
Вы хотите написать некую функцию, которую можно вызывать с любым из значений p, s, t, c?
Или Вы хотите ЭТОЙ функции передавать параметром одно из p, s, t, c ?
------------
Кстати, если p, s, t, c действительно указатели, то Ваша
sizeof(c)означает не размер структуры с, а размер указателя (т.е. всегда 2). Если Вы хотите, чтобы там был размер стрктуры, то пишитеsizeof(*c).хотим ЭТОЙ функции передавать параметром одно из p, s, t, c
чтобы было примерно так
где param - параметр (структура), указываемая в вызывающей подпрограме
так примерно
чтобы избавиться от 4 строк
заменив их одной
Прочитай про switch...case еще. ;)
Ну и передавай тогда type и твой param в параметрах. Или количество параметров критично?
switch case не при делах, количество параметров не критично.
я не умею правильно написать вызов
разжуйте на примере
для этой конструкции необходимы заголовок (header) сообщение (param) и макс размер сообщения (sizeof (*param)
т.к. сообщения в моем случае м.б. разными я и хочу их передавать функции rcv как параметры
Самое тупое передавать указатель на структуру и её длину, поскольку длина и есть sizeof. Однако нам по барабану какая структура.
Указатель может быть передан, например как byte * или char *
Это навскидку
UPD и да, тип передавать не нужно.
пример приведите пожалуйста
pilnikov, есть много способов это сделать и у каждого свои ++ и --. Рассмотрим два способа.
Способ 1 (как Вам советовал kisoft)
В функции объявляем, что она принимает универсальный указатель "на что-нибудь", а при вызове передаём реальный указатель и длину структуры.
struct S { int field; // la-la-la } * s; struct P { char c; // la-la-la } * p; void MyFunction(void *p, int nSize) { // здесь нам пофиг что за структура, // знаем только, что p указывает на буфер длины nSize // la-la-la } void setup() { // Правильные вызовы выглядят так MyFunction(p, sizeof(*p)); MyFunction(s, sizeof(*s)); // А вот такие вызовы компилятор пропустит, но у нас буду с ними проблемы MyFunction(p, sizeof(*s)); MyFunction(0, sizeof(*s)); //... } void loop() { //... }Плюсы этого метода: никакого дополнительного кода, всё чисто.
Минусы: мы выключили механизм контроля типа и если по ошибке передадим функции вместо указателя что-то недопустимое (или просто передадим указатель на одну структуру, а sizeof по ошибке напишем от другой), то компилятор это пропустит и Вам придётся вылавливать труднодиагностируемую ошибку при выполнении.
Т.е. этим способом можно пользоваться, но аккуратно и внимательно, т.к. контроль ошибок по типам отключён и всё держится на Вашей внимательности.
Второй способ
сохраняет котроль типов и делает это за счёт т.н. "перегрузки операций". Т.е. мы объявляем несколько функций с одинаковым именем и разными параметрами. Компилятор сам разберётся какую вызывать (по типу аргумента), а если мы передадим левый тип - будет сильно ругаться и т.о. убережёт нас от поиска ошибки времени выполнения. Смотрите.
struct S { int field; // la-la-la } * s; struct P { char c; // la-la-la } * p; void MyFunction(struct P *ptr) { // 1 // здесь работаем только со структурой P // её длина нам известна, - sizeof(struct P) // la-la-la } void MyFunction(struct S *ptr) { // 2 // здесь работаем только со структурой S // её длина нам известна, - sizeof(struct S) // la-la-la } void setup() { // Правильные вызовы выглядят так MyFunction(p); // вызовется 1 MyFunction(s); // вызовется 2 // А вот такие вызовы обругает компилятор int n; MyFunction(&n); MyFunction(0); //... } void loop() { //... }Минус тут - лишний код.
Выбирайте.
Можно объединить оба метода. Сделать универсальную функцию и вызывать её из оберток второго метода, плюс обёртки сделать инлайном, тогда вообще будет шоколад.
вообщем начал пробовать
функция слегка преобразилась и стала такой
bool Lnk (bool mode, byte node, uint8_t type, void *u, int nSize) { bool ok = false; network.update(); RF24NetworkHeader header(node, type); if (mode) { ok = network.write(header, u, nSize); Serial.print("Send to "); } else { ok = network.read (header, u, nSize); Serial.print("Read from "); } Serial.print(node, HEX); Serial.print(" type "); Serial.print(type, HEX); Serial.print(" Size "); Serial.print(nSize, DEC); if (ok) Serial.println(" OK"); else Serial.println(" Fail"); return ok; }вызов этой функции
void loop() { //Отправляем инфу часовым клиентам (NRF24L01) if ( millis() - int1 < 0 || millis() - int1 > 20000 ) { int1 = millis(); p->Pn = 5; Lnk(true, 0x2, TYPE_PING, p, sizeof(*p)); if (Lnk(false, 0x2, TYPE_METEO1, s, sizeof(*s))) snrDisplay(); } if ( millis() - int2 < 0 || millis() - int2 > 25000 ) { int2 = millis(); c->Time = now(); digitalClockDisplay(); Lnk(true, 0x3, TYPE_TIME1, c, sizeof(*c)); Lnk(true, 0x4, TYPE_TIME1, c, sizeof(*c)); Lnk(true, 0x4, TYPE_METEO1, s, sizeof(*s)); Lnk(true, 0x4, TYPE_TABLO1, t, sizeof(*t)); } }результат работы
Так имя Вы уже потеряли, Вы ведь решили передавать только указатель и длину структуры. Если длины разные - выводите длину и убеждайтесь по ней. Или заведите ещё параметр и передавайте имя как строку.
ну и бог с ним с именем
У Вас есть тип, это и есть имя, нет?
нет немного не так
#ifndef ClassCoder_h #define ClassCoder_h // Адрес NRF24L01 для сервера const uint16_t nrf24_server_node = 0x0; const uint8_t nrf24_channel = 90; // Адреса узлов const uint16_t nrf24_chasy_node = 0x3; const uint16_t nrf24_sensor_node = 0x2; const uint16_t nrf24_tablo_node = 0x4; // Адреса 1-10 сенсоры температуры // Тип пакета RF24NetworkHeader.type #define TYPE_PING 0x01 //Пакет с PING #define TYPE_METEO1 0x11 //Метеосенсор 1-го типа #define TYPE_TABLO1 0x13 //Погода из интернета #define TYPE_TIME1 0x20 //Время //Структура данных для проверки доступности абонента struct TSPng { uint8_t Pn; //Номер пакета }*p; //Структура данных для метеосенсора struct TSSnr { float iT; //Температура (внутри) float P; //Давление float iH; //Влажность (внутри) float oT; //Температура (снаружи) float oH; //Влажность (снаружи) }*s; //Структура данных для часов struct TSClk { time_t Time; //Время }*c; //Структура данных для табла struct TSTbl { float pT; //Температура (прогноз) float pP; //Давление (прогноз) float pH; //Влажность (прогноз) unsigned long wind; //Направление и скорость ветра unsigned long prec; //Осадки и облачность }*t; #endif