РЕШЕНО Extern для объектов

Тема в разделе "ESP8266, ESP32", создана пользователем Levvarrr, 29 окт 2022.

  1. Levvarrr

    Levvarrr Нуб

    Всем привет!
    Возник вопрос с которым не могу разобраться.
    Пишу на platformio для esp32 с framework arduino. И проблема заключается в использовании объектов в других файлах программы.
    Поясню.
    Программа состоит из нескольких файлах .срр. К ним имеются соответствующие файлы .h.
    Если например в одном вайле мы объявляем перемену, то что бы использовать её в другом файле необходимо её объявить со словом "extern". Но это работает только с переменными.
    А как быть с объектами?
    Например объявляем объект память:
    AT24Cxx eep(0x57, 32);
    "eep" доступна только в том файле в котором её объявили.
    Другой файл epp не видит.
    И даже объявление extern AT24Cxx eep(0x57, 32); не помогает.

    Скажите пожалуйста как правильно обращать к объектам из других файлов?
     
  2. Asper Daffy

    Asper Daffy Иксперд

    В общем случае, следует различать определение и объявление объекта. Определяется он только в одном месте. А объявляться может в любых местах.

    Так вот, в определении слово extern НЕ используется. Оно используется в объявлении и означает, что мы просто объявляем, что где-то есть объект такого типа и с таким именем. В свою очередь в объявлении (со словом extern) не используется инициализация.

    Никакой разницы между объектами разных типов нет. Всё работает одинаково.

    Что касается Вашего заявления:
    то Вы однозначно накосячили. Но, поскольку код не приведён, я не могу сказать в чём именно (тут есть миллион способов накосячить).

    Сделайте своё "например" в виде кода. Вам надо сделать три файла из нескольких строк каждый. В одном .cpp определите объект, во втором .cpp используйте его, а в третьем .h - объявите. Если сделаете и оно не заработает, то приведите код, я скажу в чём косяк.
     
    DetSimen нравится это.
  3. Levvarrr

    Levvarrr Нуб

    Main.cpp
    Код (C++):
    #include <Arduino.h>
    #include <AT24Cxx.h>
    #include <A.h>

    AT24Cxx eep(0x57, 32);

    void setup()
    {
      eep.write(0, 111); //По адресу 0 записываем число 111
    }

    void loop()
    {
      int temp = Raedeep(); //Считываем значение с адреса 0
    }
    A.cpp
    Код (C++):
    #include <A.h>

    int Raedeep()
    {
       return eep.read(0);
    }
    A.h
    Код (C++):
    #ifndef A_H
    #define A_H

    #include <AT24Cxx.h>
    extern AT24Cxx eep(0x57, 32);
    int Raedeep();

    #endif
    Ошибка компилятора

    Код (Text):
    In file included from src/A.cpp:1:
    include/A.h:5:19: warning: 'eep' initialized and declared 'extern'
    extern AT24Cxx eep(0x57, 32);
                       ^
    In file included from src/main.cpp:3:
    include/A.h:5:19: warning: 'eep' initialized and declared 'extern'
    extern AT24Cxx eep(0x57, 32);
                       ^
    src/main.cpp:5:12: error: redefinition of 'AT24Cxx eep'
    AT24Cxx eep(0x57, 32);
                ^
    In file included from src/main.cpp:3:
    include/A.h:5:16: note: 'AT24Cxx eep' previously declared here
    extern AT24Cxx eep(0x57, 32);
                    ^~~
    Archiving .pio\build\esp32doit-devkit-v1\libFrameworkArduino.a
    *** [.pio\build\esp32doit-devkit-v1\src\main.cpp.o] Error 1
    Я не понимаю как дать понять что объект уже задан в другом файле......
    С переменными и структурами "extern" работает...... А вот с объектами не очень.....
    И в интернете все примеры только с переменными...
     
  4. Asper Daffy

    Asper Daffy Иксперд

    Вот посмотрите, я Вам писал:
    Потом компилятор Вам написал:
    Вы читаете, что Вам пишут?

    Уберите нахрен инициализацию из файла .h, оставьте только "extern AT24Cxx eep;" и будет Вам счастье.

    Нет никакой разницы в типах, просто нужно понимать, что делаешь. Объявление со словом extern означает, что здесь этого объекта нет, он где-то в другом месте. Так какая нахрен инициализация?

    И, кстати, добавьте там же слово extern перед объявлением функции Raedeep, чего Вы её обижаете? Правильно там писать extern int Raedeep ...
     
    Levvarrr нравится это.
  5. Levvarrr

    Levvarrr Нуб

    Точно! Заработало:) Спасибо!


    Так она записана как прототип... А для прототип дополнительный extern не нужен.
     
  6. Asper Daffy

    Asper Daffy Иксперд

    Не нужен, но лишним не будет - а при некоторых условиях может и полезной оказаться - поможет LTO оптимизировать код. Да и просто, для тех файлов, в которых она используется - это явное указание на то, что она определена в другом месте. А явные вещи всегда лучше неявных - при случает помогают тем же оптимизаторам (вроде LTO).
     
    DetSimen и Levvarrr нравится это.