Неразрешенная ссылка на общедоступную функцию из библиотеки

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

Documents
├── Some/Path/To/Folder
│   └── firmware.ino
└── Arduino
    └── libraries
        ├── error
        │   ├── error.h
        │   └── error.cpp
        ├── lmp91000
        │   ├── lmp91000.h
        │   └── lmp91000.cpp
        └── tps7a7100
            ├── tps7a7100.h
            └── tps7a7100.cpp

Как lmp91000.h, так и tps7a7100.h имеют #include "../ошибка/ошибка.h" и могут обращаться к переменным и функциям, объявленным в error.h и error.cpp просто отлично.

firmware.ino включает в себя все три библиотеки, как и следовало ожидать, и может создавать экземпляры классов, определенных как в lmp91000, так и в tps7a7100, и использовать их методы (которые зависят от ошибки). Я также могу создавать экземпляры структуры (ОШИБКИ), определенной в error.h из firmware.ino, однако я не могу получить доступ к функциям из error.h и error.cpp. Полученная ошибка является

firmware.ino:19: undefined reference to `LOG_E(ERROR)'

Однако, когда я удаляю охранников в error.h, эта ошибка больше не появляется (подразумевая, что LOG_E может быть устранен), но я получаю ожидаемые ошибки нескольких определений, поскольку существует несколько ошибок #include.h.

Мои мысли таковы, что из-за ошибки guards не включается в место, где у скетча есть доступ к функциям, но я могу быть полностью отключен от этого. Я знаю, что должен быть способ обойти это, так как я могу получить доступ к Wire.h, например, из прошивки.ino, даже если это включено в lmp91000.h - как мне это решить?

прошивка.ino

#include <error.h>
#include <lmp91000.h>
#include <tps7a7100.h>
#include <Wire.h>

lmp91000 pot(12);
tpsa7100 vreg(10,9,8,7,6,5,4);

void setup() {
    Wire.begin();
    Serial.begin(115200);
    while(!Serial);
    vreg.enable();
    pot.enable();
    ERROR misc;
    misc.errorCode = 0x50;
    LOG_E(misc);
}

void loop() {
}

ошибка.h

#ifndef error_h_included
#define error_h_included

#include "Arduino.h"


// Структура ошибок
typedef struct{
    int errorCode;
    char const *errorName;
    char const *errorDesc;
    bool isFatalError;
    bool shouldRetry;
}ERROR;

// Глобальные типы ошибок
const ERROR E_SUCCESS = {0x00, "E_SUCCESS", "Success", false, false};
const ERROR E_INVALID_ARG = {0x10, "E_INVALID_ARG", "Invalid argument passed", true, false};
const ERROR E_I2C_NACK_ADDR = {0x20, "E_I2C_NACK_ADDR", "NACK on I2C address byte", false, true};
const ERROR E_I2C_NACK_DATA = {0x21, "E_I2C_NACK_DATA", "NACK on I2C data byte", false, true};
const ERROR E_I2C_BUFF_LEN = {0x22, "E_I2C_BUFF_LEN", "Transmit Data too long for I2C buffer", true, false};
const ERROR E_I2C_ERROR = {0x23, "E_I2C_ERROR", "Undefined I2C Error", true, false};
const ERROR E_I2C_TARGET_DISABLED = {0x24, "E_I2C_TARGET_DISABLED", "Target device for I2C comms disabled", false, false};
const ERROR E_I2C_READ_ERROR = {0x25, "E_I2C_READ_ERROR", "I2C Data could not be read", false, false};
const ERROR E_I2C_WRITE_ERROR = {0x26, "E_I2C_WRITE_ERROR", "Attempting to write zero bytes to I2C bus", false, false};

// Определения функций
bool E(ERROR error_struct);
void LOG_E(ERROR error_struct);
ERROR WireErrorDecode(int code); 


#endif

error.cpp

#include "error.h"


// Функции Обработки Ошибок

// E(ERROR)
// Оцените успешность ошибки
// Возвращает 0, если ошибка является ошибкой успеха
// Возврат >0, если ошибка не является ошибкой успеха
bool E(ERROR error_struct) {
    return (int)(error_struct.errorCode & 0xF0);
}

// LOG(ERROR)
// Log the error 
void LOG_E(ERROR error_struct) {
    Serial.print(error_struct.errorCode);
    Serial.print("\t");
    Serial.print(error_struct.errorName);
    Serial.print("\t");
    Serial.println(error_struct.errorDesc);
}

// WireErrorDecode(code)
// Decode Wire.EndTransmission error codes
ERROR WireErrorDecode(int code) {
    switch(code) {
        case 0:
            return E_SUCCESS;
        case 1:
            return E_I2C_BUFF_LEN;
        case 2:
            return E_I2C_NACK_ADDR;
        case 3:
            return E_I2C_NACK_DATA;
        case 4:
            return E_I2C_ERROR;
        default:
            return E_INVALID_ARG;
    }
}

Обновление: Эти ошибки, похоже, относятся к конкретной плате - см. Вопрос здесь

, 👍0

Обсуждение

"... подразумевая, что LOG_E может быть разрешен". Нет, это не подразумевает ничего подобного. "Неопределенная ссылка" - это ошибка компоновщика. А без включенной защиты вы просто никогда не доберетесь до стадии связывания из-за лавины других ошибок., @AnT

проверьте, являются ли определения guard уникальными, @Juraj

Вы добавили файлы library.properties в свои библиотеки? По крайней мере, протестируйте перемещение всех файлов библиотеки в папку скетча. Это может дать некоторую дополнительную информацию о сборке этого "уникального" Arduino :), @Mikael Patel

@MikaelPatel перемещение библиотек в папку скетча позволяет ей компилироваться без ошибок. Я не понимаю, почему это может иметь значение, хотя, поскольку изначально они находились в папке libaries пути Arduino. Кроме того, почему это повлияет только на 101, а не на какую-либо другую плату, как описано в связанном вопросе, @omar_hussein

Вы уверены, что имя "ошибка" еще не занято какой-либо существующей библиотекой на 101? Попробуйте переименовать свою библиотеку из "ошибка" во что-то другое., @AnT

Следующий шаг-включить подробный режим при сборке в среде IDE Arduino, чтобы вы получили фактические командные строки компиляции и компоновки. Изучите выходные данные, и вы найдете свою ошибку., @Mikael Patel


1 ответ


1

Ошибка имени файла.h-неподходящее название для библиотеки. Некоторые компиляторы и ядра (такие как ядра ESP32 и Кюри) имеют собственную ошибку файла.h, которая будет использоваться предпочтительнее вашей.

Вместо этого назовите свою библиотеку чем-нибудь более разумным.

,