Jump to content

    
Sign in to follow this  
Метценгерштейн

ошибка при компиляции С++

Recommended Posts

4 hours ago, x893 said:

Статический метод может так вызываться.

имя_класса.статический_метод(...)

Книги - великая вешь, если умеешь читать (это для ТС)

Я прекрасно знаю, что статический метод может вызываться без объявления объекта. Сразу его можно вызвать. Я более того, знаю, что для всех объектов этого класса со статическим методом, он всегда будет один, и поменяв значение в одном объекте, оно изменится во всех.

Но, давайте честно, разве речь в теме про это? Я разве имею проблемы со статическим методом и непониманием его? НЕТ. Нету здесь статического метода. 

4 hours ago, esaulenka said:

Код из первого сообщения похож на официальный пример: https://github.com/espressif/arduino-esp32/blob/master/libraries/WiFi/examples/WiFiClientEvents/WiFiClientEvents.ino
Можно предположить, что он работает.

Какой магией при подключении wifi.h подтягивается соотв. кусок BSP - я не знаю. Изучение ESP в планах есть, но всё никак руки не дойдут...

да, я и привел официальный пример. Полагаю, что он работает. Но не в моем случае. И , как мне кажется, на ровном месте ошибка.

Share this post


Link to post
Share on other sites
1 hour ago, Метценгерштейн said:

Линукс, отладки нет никакой, еще и с компиляцией проблемы.

Линукс, на мой взгляд, наоборот, всё упрощает.

Отладка - вещь крайне редко полезная. Нужно полагаться на тесты и отладочную печать. Но если хотите отладчик, то воспользуйтесь gdb, как вам уже предложили.

Вам компилятор говорит, что вы неправильно используете нестатический метод. Такое бывает, когда вы пытаетесь передать метод класса как указатель на функцию, или когда вы используете члены класса, как значение аргумента по умолчанию.

Вот и подумайте, где вы это сделали.

Вы привели ошибку в использвании объекта класса WiFiClass, но не привели определение класса WiFiClass, вы сказали, что вы отнаследовались от этого класса, но не привели то, как вы отнаследовались, вы используете метод onEvent, но не привели определение метода onEvent, вы передаёте в качесте параметра WiFiEvent, и это единственное, что вы показали, среди гораздо большего количества мусора. И-то, похоже, случайно: она оказалась в файле с примером.

Это всё говорит, что вы вообще не понимаете, что делаете.

Например, тот самый WiFiEvent:

void WiFiEvent(WiFiEvent_t event)
{
    Serial.printf("[WiFi-event] event: %d\n", event);

    switch (event)
    {
    case SYSTEM_EVENT_STA_GOT_IP:
        Serial.println("WiFi connected");
        Serial.println("IP address: ");
        Serial.println(WiFi.localIP());
        break;
    case SYSTEM_EVENT_STA_DISCONNECTED:
        Serial.println("WiFi lost connection");
        break;
    }
}

Печатает IP адрес объекта WiFi, а не вашего wifi.

Edited by one_eight_seven

Share this post


Link to post
Share on other sites
1 hour ago, Метценгерштейн said:

Пожалуйста, из этой книги, приведите мне абзац, где есть ответ на мой вопрос- почему ошибка. Иначе- это просто с понтом дела пост был. Что по факту и есть.

Проект сложный. Сложный не в коде, а в подходе к написанию. Линукс, отладки нет никакой, еще и с компиляцией проблемы. Потому и вопросы такие. И во всех своих темах я даю много информации по мере поступления вопросов. Всё сразу сказать невозможно.

 

Как это нет отладки ?

https://mcuoneclipse.com/2019/09/22/eclipse-jtag-debugging-the-esp32-with-a-segger-j-link/

Share this post


Link to post
Share on other sites
3 minutes ago, x893 said:

Проект устроен так (удаленное устройство), что из отладки у меня только логи возможны.

19 minutes ago, one_eight_seven said:

Печатает IP адрес объекта WiFi, а не вашего wifi.

Вот мой метод WiFiEvent

Смысла это много не дает. Не компилится он всё равно.

void WiFiClient::WiFiEvent(WiFiEvent_t event) {
    Serial.printf("[WiFi-event] event: %d\n", event);

    switch (event) {
        case SYSTEM_EVENT_WIFI_READY: 
            Serial.println("WiFi interface ready");
            break;
        case SYSTEM_EVENT_SCAN_DONE:
            Serial.println("Completed scan for access points");
            break;
        case SYSTEM_EVENT_STA_START:
            Serial.println("WiFi client started");
            break;
        case SYSTEM_EVENT_STA_STOP:
            Serial.println("WiFi clients stopped");
            break;
        case SYSTEM_EVENT_STA_CONNECTED:
            Serial.println("Connected to access point");
            break;
        case SYSTEM_EVENT_STA_DISCONNECTED:
            Serial.println("Disconnected from WiFi access point");
            break;
        case SYSTEM_EVENT_STA_AUTHMODE_CHANGE:
            Serial.println("Authentication mode of access point has changed");
            break;
        case SYSTEM_EVENT_STA_GOT_IP:
            Serial.print("Obtained IP address: ");
            Serial.println(WiFi.localIP());
            break;
        case SYSTEM_EVENT_STA_LOST_IP:
            Serial.println("Lost IP address and IP address is reset to 0");
            break;
        case SYSTEM_EVENT_STA_WPS_ER_SUCCESS:
            Serial.println("WiFi Protected Setup (WPS): succeeded in enrollee mode");
            break;
        case SYSTEM_EVENT_STA_WPS_ER_FAILED:
            Serial.println("WiFi Protected Setup (WPS): failed in enrollee mode");
            break;
        case SYSTEM_EVENT_STA_WPS_ER_TIMEOUT:
            Serial.println("WiFi Protected Setup (WPS): timeout in enrollee mode");
            break;
        case SYSTEM_EVENT_STA_WPS_ER_PIN:
            Serial.println("WiFi Protected Setup (WPS): pin code in enrollee mode");
            break;
        case SYSTEM_EVENT_AP_START:
            Serial.println("WiFi access point started");
            break;
        case SYSTEM_EVENT_AP_STOP:
            Serial.println("WiFi access point  stopped");
            break;
        case SYSTEM_EVENT_AP_STACONNECTED:
            Serial.println("Client connected");
            break;
        case SYSTEM_EVENT_AP_STADISCONNECTED:
            Serial.println("Client disconnected");
            break;
        case SYSTEM_EVENT_AP_STAIPASSIGNED:
            Serial.println("Assigned IP address to client");
            break;
        case SYSTEM_EVENT_AP_PROBEREQRECVED:
            Serial.println("Received probe request");
            break;
        case SYSTEM_EVENT_GOT_IP6:
            Serial.println("IPv6 is preferred");
            break;
        case SYSTEM_EVENT_ETH_START:
            Serial.println("Ethernet started");
            break;
        case SYSTEM_EVENT_ETH_STOP:
            Serial.println("Ethernet stopped");
            break;
        case SYSTEM_EVENT_ETH_CONNECTED:
            Serial.println("Ethernet connected");
            break;
        case SYSTEM_EVENT_ETH_DISCONNECTED:
            Serial.println("Ethernet disconnected");
            break;
        case SYSTEM_EVENT_ETH_GOT_IP:
            Serial.println("Obtained IP address");
            break;
        default: 
            break;
    }
}

 

WiFi.h

#ifndef WiFi_h
#define WiFi_h

#include <stdint.h>

#include "Print.h"
#include "IPAddress.h"
#include "IPv6Address.h"

#include "WiFiType.h"
#include "WiFiSTA.h"
#include "WiFiAP.h"
#include "WiFiScan.h"
#include "WiFiGeneric.h"

#include "WiFiClient.h"
#include "WiFiServer.h"
#include "WiFiUdp.h"

class WiFiClass : public WiFiGenericClass, public WiFiSTAClass, public WiFiScanClass, public WiFiAPClass
{
public:
    using WiFiGenericClass::channel;

    using WiFiSTAClass::SSID;
    using WiFiSTAClass::RSSI;
    using WiFiSTAClass::BSSID;
    using WiFiSTAClass::BSSIDstr;

    using WiFiScanClass::SSID;
    using WiFiScanClass::encryptionType;
    using WiFiScanClass::RSSI;
    using WiFiScanClass::BSSID;
    using WiFiScanClass::BSSIDstr;
    using WiFiScanClass::channel;

public:
    void printDiag(Print& dest);
    friend class WiFiClient;
    friend class WiFiServer;
    friend class WiFiUDP;
};

extern WiFiClass WiFi;

#endif

WiFi.cpp

#include "WiFi.h"

extern "C" {
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <string.h>
#include <esp_err.h>
#include <esp_wifi.h>
#include <esp_event_loop.h>
}


// -----------------------------------------------------------------------------------------------------------------------
// ---------------------------------------------------------- Debug ------------------------------------------------------
// -----------------------------------------------------------------------------------------------------------------------


/**
 * Output WiFi settings to an object derived from Print interface (like Serial).
 * @param p Print interface
 */
void WiFiClass::printDiag(Print& p)
{
    const char* modes[] = { "NULL", "STA", "AP", "STA+AP" };

    wifi_mode_t mode;
    esp_wifi_get_mode(&mode);

    uint8_t primaryChan;
    wifi_second_chan_t secondChan;
    esp_wifi_get_channel(&primaryChan, &secondChan);

    p.print("Mode: ");
    p.println(modes[mode]);

    p.print("Channel: ");
    p.println(primaryChan);
    /*
        p.print("AP id: ");
        p.println(wifi_station_get_current_ap_id());

        p.print("Status: ");
        p.println(wifi_station_get_connect_status());
    */

    wifi_config_t conf;
    esp_wifi_get_config(WIFI_IF_STA, &conf);

    const char* ssid = reinterpret_cast<const char*>(conf.sta.ssid);
    p.print("SSID (");
    p.print(strlen(ssid));
    p.print("): ");
    p.println(ssid);

    const char* passphrase = reinterpret_cast<const char*>(conf.sta.password);
    p.print("Passphrase (");
    p.print(strlen(passphrase));
    p.print("): ");
    p.println(passphrase);

    p.print("BSSID set: ");
    p.println(conf.sta.bssid_set);
}

WiFiClass WiFi;

 

23 minutes ago, one_eight_seven said:

Например, тот самый WiFiEvent:

Я его привел для примера из общего примера. Понятно, что не использую его в чистом виде. Но сам метод и его передача в ф-ю не проходят.

24 minutes ago, one_eight_seven said:

вы сказали, что вы отнаследовались от этого класса, но не привели то, как вы отнаследовались,

WiFiClass wifi;

Вернее, я не наследовался от него. Этот класс, это имел ввиду, сам наследник кучи всего:

class WiFiClass : public WiFiGenericClass, public WiFiSTAClass, public WiFiScanClass, public WiFiAPClass

Невозможно весь проект в одном посте описать. Говорите, какие куски кода привести, и чего забыл указать? Я дополню.

29 minutes ago, one_eight_seven said:

Вам компилятор говорит, что вы неправильно используете нестатический метод. Такое бывает, когда вы пытаетесь передать метод класса как указатель на функцию, или когда вы используете члены класса, как значение аргумента по умолчанию.

Вот и подумайте, где вы это сделали.

Вот тут я не понимаю что происходит из этого у меня.

Share this post


Link to post
Share on other sites
16 minutes ago, Метценгерштейн said:

Вот мой метод WiFiEvent

Смысла это много не дает. Не компилится он всё равно.

А чтение даёт смысл?

Ведь в том же посте, откуда вы выдернули окончание написано, что нельзя передавать члены класса в качестве указателей на функции. И вот, вы НАКОНЕЦ-ТО привели тот самый кода кусок, где вы именно это делаете.

16 minutes ago, Метценгерштейн said:

Вот тут я не понимаю что происходит из этого у меня. 

Да. это видно.

Вы пытаетесь передать указатель на метод класса туда, куда надо передавать указатель на функцию. Это не получится. Не получится передать указатель на метод класса.

А теперь самое главное - Зачем? Вы берёте кусок кода из примера, где показывается как натянуть сову на глобус (применить WiFiEvent_t, если неизвестно как и зачем его применять), а зачем?

Edited by one_eight_seven

Share this post


Link to post
Share on other sites

Мама дорогая!

Если совсем тяжело, то возьмите любую IDE (VSCode, VS, Exlipse, ...) с подсказками и сделайте простой проект из этих классов.

Наберёте

WiFi.

и он Вам нарисует какие методы, свойства и события можно использовать.

 

Share this post


Link to post
Share on other sites

В первом вашем посте с кодом примера не было метода WiFiEvent. Была такая функция. Она была просто функцией, а не методом класса. Вы же решили сделать её методом класса. И после этого появилась ошибка компиляции. Выводы делайте сами - кто виноват и что делать.

Share this post


Link to post
Share on other sites
26 minutes ago, Метценгерштейн said:

Я его привел для примера из общего примера. Понятно, что не использую его в чистом виде. Но сам метод и его передача в ф-ю не проходят.

Мужик роется в луже под фонарём.

Подходит другой мужик:

- Что, потерял что-то?
- Да, ключи потерял, вот, ищу.
- Ну, давай, помогу.
Через полчаса в луже уже четыре мужика шарят, найти не могут, тут один спрашиват:
- Мужик, ты точно тут ключи потерял?
- Не, я их во-о-он там, у магазина потерял.
- Так чего ты их тут ищешь, а не там?!?
- А тут светлее!

Share this post


Link to post
Share on other sites
11 minutes ago, Darth Vader said:

В первом вашем посте с кодом примера не было метода WiFiEvent. Была такая функция. Она была просто функцией, а не методом класса. Вы же решили сделать её методом класса. И после этого появилась ошибка компиляции. Выводы делайте сами - кто виноват и что делать.

Была ф-ей, работало, наверное. Метод класса- не хочет. Вывод- нельзя так делать.

21 minutes ago, one_eight_seven said:

Не получится передать указатель на метод класса.

Получается, вот ответ. Функцию можно так передавать, а метод класса (ту же ф-ю, но в составе класса) уже нет. Я действительно, не знал этого.

Хорошо, а если этот метод сделать статическим- так можно тогда?

 

Share this post


Link to post
Share on other sites
5 minutes ago, Метценгерштейн said:

Хорошо, а если этот метод сделать статическим- так можно тогда? 

Вот у меня тоже linux. Три минуты, и:
tst.cpp:
 

#include <iostream>

using namespace std;

typedef string (*fn_type)(void);

class A {
    public:
        static string who_am_i(){
            return "static_method";
        }
};

class B {
    public:
        void my_print(fn_type fn) {
            cout << "My_print: " << fn() << endl;
        }
};

int main() {
    B b_obj;
    b_obj.my_print(A::who_am_i);
}

Далее:
 

$ g++ tst.cpp
$ ./a.out
My_print: static_method

 

Share this post


Link to post
Share on other sites
14 minutes ago, Метценгерштейн said:

Получается, вот ответ. Функцию можно так передавать, а метод класса (ту же ф-ю, но в составе класса) уже нет. Я действительно, не знал этого.

Хорошо, а если этот метод сделать статическим- так можно тогда?

Можно извернуться и таки передать указатель на метод класса. Точнее какого-то экземпляра реализации класса. Он (метод) оказавшись в незнакомой среде, чешет репу, "где я"  ?  Статический метод - общий для всех экземпляров-реализаций класса. 

Могобыть я что не так понимаю ? :russian_ru:

 

Share this post


Link to post
Share on other sites
11 minutes ago, k155la3 said:

Могобыть я что не так понимаю ? :russian_ru:

Ага. Указатель на нестатический метод не передать. Взять можно, а передать - нет.
И опять таки, если смотреть мой пример выше, если сделать who_am_i нестатическим, то его тип будет уже не:
 

string (*)(void)

а
 

string(A::*)(void)

и без объекта типа A он не имеет вообще никакого смысла (примерно то, что вы указали как "чешет репу").
Насколько я понял, нестатические методы имеют скрытый параметр, соответствующий указателю this. А его нам передать просто нечем.
Поэтому, если каким-то чудом нужно передать именно указатель на нестатический метод конкретного экземпляра, то можно обернуть в обычную функцию вызов метода из экземпляра, и передавать уже эту обычную функцию.
как это и было сделано в изначальном примере WiFiEvent, где был вызов WiFi.localIp().

Edited by one_eight_seven

Share this post


Link to post
Share on other sites
1 hour ago, one_eight_seven said:

Отладка - вещь крайне редко полезная.

Разговор про отладку начал я в соседней теме, когда автор сломал что-то в кишках flatbuffer'а. Что именно сломал, коллективный разум не понял (впрочем, никто из присутствующих не знаком близко с flatbuffer). Вот там без гуляний по шагам с пристальным просмотром всех переменных некомфортно.

 

6 minutes ago, one_eight_seven said:

Указатель на нестатический метод не передать.

В комплекте из двух указателей - на экземпляр класса и на сам метод - можно и передать, и использовать.

Тут даже где-то была тема про делегаты в с++, где мы это обсуждали.

 

Но один указатель на "голую" функцию проще этой магии на порядок.

Share this post


Link to post
Share on other sites
13 minutes ago, esaulenka said:

В комплекте из двух указателей - на экземпляр класса и на сам метод - можно и передать, и использовать.

Вы про это?
 

Spoiler

#include <iostream>

using namespace std;

class A {
    public:
        string who_am_i () {
            return "non static method";
        }
};

typedef string (A::*fnp)(void);

class B {
    public:
        void my_print(A* p, fnp mp) {
            cout << "My_print: " << (p->*mp)() << endl;
        }
};

int main() {
    B b_obj;
    A a_obj;

    fnp p = &A::who_am_i;

    b_obj.my_print(&a_obj, p);
}

 

 

Share this post


Link to post
Share on other sites
50 minutes ago, Метценгерштейн said:

Функцию можно так передавать, а метод класса (ту же ф-ю, но в составе класса) уже нет.

Можно, но не в вашем случае. Метод OnEvent ожидает в параметре указатель на функцию, а не на метод класса. У нестатических методов всегда есть неявный параметр this - указатель на объект, от имени которого вызывается метод.

Про указатели на функции-члены класса и их синтаксис, объявление и использование можно почитать тут.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this