21 Востаннє редагувалося ReAl (16.02.2018 10:48:57)

Re: У функцію вказівник на змінну, а далі той вказівник в ще одну функцію

Yola написав:

Якщо хочете, то можете залишити обгортки, як-от:

void Blynk_virtualWriteFloat(int pin, float value) {
    char *chvalue = (char*)(&value);
    Blynk_virtualWriteString(pin, chvalue, sizeof(float));
}

У спільну функцію з обгортки крім розміру ще тип треба передавати, BLYNK_TYPE_INT і компанію:

void   Blynk_virtualWrite(int pin, int type, void *pdata, size_t size);
Подякували: Yola, taburyak2

22

Re: У функцію вказівник на змінну, а далі той вказівник в ще одну функцію

Yola написав:

Мати три функції з майже ідентичним кодом - небезпечно.

Погоджуюсь.

Yola написав:

Якщо хочете, то можете залишити обгортки, як-от:

Супер! Дякую за ідею. Таке тільки з досвідом приходить.

23

Re: У функцію вказівник на змінну, а далі той вказівник в ще одну функцію

ReAl написав:

У спільну функцію з обгортки крім розміру ще тип треба передавати, BLYNK_TYPE_INT і компанію:

void   Blynk_virtualWrite(int pin, int type, void *pdata, size_t size);

А ви уважні  ;D
Так і зробив  *OK*

24

Re: У функцію вказівник на змінну, а далі той вказівник в ще одну функцію

Перепрошую що дублюю повідомлення, але в цій гілці більше шансів на відповідь, бо це стосується все ж таки мови Сі, а не залізяки.

Не можу я подолати ці хитрощі з передпроцесором.
Спробую пояснити що хочу, а ви вже направте в потрібне русло.
Я приймаю пакет даних, де є номер шпильки і дані, які на тій шпильці є. Номер шпильки - число від 0 до 127, а данні - масив з char'ів.
В заголовний файл почав щось шкрябати на кшталт такого (просто для попробувати розібратись):

#define BLYNK_WRITE_MY(pin) void Blynk_Write ## pin(void)

А в файлі main написав таку функцію:

BLYNK_WRITE_MY(20)
{
 
}

Ну а далі в мене ступор. Що треба зробити щоб коли я прийняв пакет даних для 20-тої шпильки в мене в головній програмі main викликалась функція BLYNK_WRITE_MY(20). Ну треба ще передати туди в середину ще й масив з char'ів.
Не знаю навіть що гуглити. Допоможіть будь ласка.

25

Re: У функцію вказівник на змінну, а далі той вказівник в ще одну функцію

Bartash, а який сенс у такому макро?
Ну і є слово "ніжка".

26

Re: У функцію вказівник на змінну, а далі той вказівник в ще одну функцію

Мені до вподоби шпилька. Бо оперую віртуальним піном. Віртуальний пін не є ніжкою, а пін імпортне слово. Тому я, як носій живої мови, зробив такий вибір і таким чином її, мову, збагачую і урізноманітнюю :)
Щодо коду, завтра спробую. Пан koala в сусідній гілці теж запропонував варіянт.

27

Re: У функцію вказівник на змінну, а далі той вказівник в ще одну функцію

О, я здається зрозумів, ви хочете побудувати ім'я функції під час виконання. Це не підхід компілюваних мов, так можна в інтерпретованих мовах. Навіщо вам це потрібно, скидається, що проблема в чомусь іншому. Чому не можна викликати

Blynk_Write(pin, pchar);

або

switch (pin) {
   ...
   20: Blynk_Write20(pchar);
   ...
}

28 Востаннє редагувалося taburyak (20.02.2018 10:26:16)

Re: У функцію вказівник на змінну, а далі той вказівник в ще одну функцію

Yola написав:

О, я здається зрозумів, ви хочете побудувати ім'я функції під час виконання.

Ні, не так і не то.
Створюю таку собі "прокладку" для STM32 між бібліотекою blynk яка "крутиться" на esp8266. Хочу зробити максимально "прозоро". В бібліотеці blynk якось хитро зроблено, що коли користувач оголосив в коді функцію типу:

BLYNK_WRITE(vPIN)
{
    int value = param.asInt();
}

Де vPIN - номер віртуальної шпильки наприклад - "0". То коли на сервері стаються зміни на цій шпильці, дані тієї шпильки передаються в param який попадає в функцію BLYNK_WRITE(0), ну а користувач з того param вже здобуває, те що йому треба, наприклад число int. І також, якщо на сервері стаються зміни на шпильці "1", але для неї в коді немає функції BLYNK_WRITE(1), то нічого не відбувається, не викликається, нас це не обходить.
Так я зі сторони STM32 хочу так само зробити. Коли відбуваються якісь зміни на шпильці зі сторони серверу, ESP8266 передає пакет даних з номером шпильки і що на шпильці до STM32 і попадає в обробник. Це вже є і прекрасно працює. Тепер треба щоб було як в бібліотеці Blynk викликалась функція BLYNK_WRITE(vPIN) в основному коді з передачею param туди. Або ігнорувалось, коли в основному коді для тієї шпильки немає відповідної функції.
Я мабуть кострубато і не зрозуміло пояснюю, бо ж не розумію як це зроблено і як це називається.

29

Re: У функцію вказівник на змінну, а далі той вказівник в ще одну функцію

Щось знову, наче на простому, застряг.
Коли з серверу щось приходить для якоїсь шпильки, то з масиву data беремо номер шпильки, та дані масив char'ів на тій шпильці. Копіюємо дані шпильки в масив myParam:

if (data[MY_BLYNK_OFFSET_IO_PIN] == MY_BLYNK_READ_PIN)
    {

        char myParam[size - MY_BLYNK_OFFSET_DATA_PIN];

        for (uint8_t i = 0; i < size - MY_BLYNK_OFFSET_DATA_PIN; i++)
        {
            myParam[i] = data[i+MY_BLYNK_OFFSET_DATA_PIN];
        }

        MyWidgetInHandler handler = MyGetInHandler(data[MY_BLYNK_OFFSET_NUM_PIN]);
        handler(myParam);
    }

А далі передаємо вказівник на масив myParam у функцію, а там я хочу з масиву char, де є число в текстовому вигляді, видобути int:

MY_BLYNK_INPUT(V20)
{
    int statusLed = atoi(param); //ParamAsInt(param);

    if(statusLed == 1)
    {
        //увімкнути щось
    }
    else if(statusLed == 0)
    {
        //вимкнути щось
    }
}

Звісно що так не працює.

А коли я наперед знаю що там 1 чи 0 і беру тільки в розрахунок один, перший елемент масиву param, так:

MY_BLYNK_INPUT(V20)
{
    char ch = param[0];
    int statusLed = atoi(&ch); //ParamAsInt(param);

    if(statusLed == 1)
    {
        //увімкнути щось
    }
    else if(statusLed == 0)
    {
        //вимкнути щось
    }
}

То так працює. Але числа можуть бути не тільки одиниці (один розряд), а й весь діапазон INT.
Як викрутитись?
Передавати разом з вказівником на масив і його розмір? А потім робити копію масиву? І вже тоді згодовувати atoi()???

30

Re: У функцію вказівник на змінну, а далі той вказівник в ще одну функцію

Зробив так:
1. Передаємо вказівник на масив і розмір масиву:

MyWidgetInHandler handler = MyGetInHandler(data[MY_BLYNK_OFFSET_NUM_PIN]);
handler(myParam, sizePinDat);

2. Приймаю вказівник і розмір та передаю у функцію ParamAsInt(param, size):

MY_BLYNK_INPUT(V2)
{
    int statusLed = ParamAsInt(param, size);
    
    if(statusLed < 55)
    {
        HAL_GPIO_WritePin(LD5_GPIO_Port, LD5_Pin, GPIO_PIN_SET);
    }
    else if(statusLed > 950)
    {
        HAL_GPIO_WritePin(LD5_GPIO_Port, LD5_Pin, GPIO_PIN_RESET);
    }
}

3. Ну і сама функція ParamAsInt(param, size):

int ParamAsInt(char* ptr, uint8_t size)
{
    char number[size];

    for(int i = 0; i < size; i++)
    {
        number[i] = *(ptr++);
    }

    return atoi(number);
}

Це працює добре. Але є одне але...

А можна якимось чином передати функції ParamAsInt розмір масиву оминаючи передачу його, розміру, в функцію MY_BLYNK_INPUT(V2)???
Щоб можна було робити запис такого типу int statusLed = ParamAsInt(param);, а функція ParamAsInt отримує розмір якимось, невидимим для користувача, шляхом???

31 Востаннє редагувалося ReAl (22.02.2018 14:38:16)

Re: У функцію вказівник на змінну, а далі той вказівник в ще одну функцію

    if (data[MY_BLYNK_OFFSET_IO_PIN] == MY_BLYNK_READ_PIN) {
        size_t const parsize = size - MY_BLYNK_OFFSET_DATA_PIN; // а воно точно невід'ємне?
        char myParam[parsize+1]; // для термінатора, atoi без нього може далеко піти

        for (uint8_t i = 0; i < parsize; i++) {
            myParam[i] = data[i+MY_BLYNK_OFFSET_DATA_PIN];
        }
        // '\0' а не 0 -- щоб сторонньому читачеві (собі через пів року)
        // зрозуміліше було, що це термінатор текстового рядка
        myParam[parsize] = '\0';

        MyWidgetInHandler handler = MyGetInHandler(data[MY_BLYNK_OFFSET_NUM_PIN]);
        handler(myParam);
    }
Подякували: taburyak1

32 Востаннє редагувалося taburyak (22.02.2018 14:26:55)

Re: У функцію вказівник на змінну, а далі той вказівник в ще одну функцію

ReAl написав:

в точно невід'ємне?

Точно, там по іншому не може бути.

Ну діла, так просто. Ще набирати досвіду і набирати, щоб такі тонкощі враховувати. Мда...
По суті треба було просто в кінець додати '\0'???

В черговий раз - дякую, дякую, дякую!!!

33

Re: У функцію вказівник на змінну, а далі той вказівник в ще одну функцію

taburyak написав:
ReAl написав:

в точно невід'ємне?

Точно, там по іншому не може бути.

«якщо ти не параноїк, то це не означає, що вони за тобою не слідкують»

Подякували: taburyak, leofun012

34

Re: У функцію вказівник на змінну, а далі той вказівник в ще одну функцію

До речі, цикл for там краще замінити на memcpy(myParam, data+MY_BLYNK_OFFSET_DATA_PIN, parsize), видніше логіку процесу.
А там хай компілятор думає — викликати функцію чи зробити цикл по місцю. Хоча якось я бачив, коли компілятор такий цикл сам на виклик memcpy замінив :-)

Подякували: taburyak1

35

Re: У функцію вказівник на змінну, а далі той вказівник в ще одну функцію

Так, додати '\0'.
І тоді можна використовувати стандартну функцію strcpy.
А щоб копіювати фіксовану кількість байтів - memcpy.

Подякували: taburyak, leofun012

36

Re: У функцію вказівник на змінну, а далі той вказівник в ще одну функцію

Дякую хлопці за поради. Я їх любо сприймаю. Перевірку на від'ємне число додам. Цикли поміняю на memcpy.