множественное определение SomeFuction. Не знаю, как исправить

Я пишу приложение Arduino (используя platformIO в VSCode) и включаю внешнюю библиотеку CAN (FlexCAN_T4). Я хочу определить все мои обратные вызовы обработчика протоколов/сообщений в отдельном файле (protocol.cpp) и ссылаться на них из моего основного файла (main.cpp). Поэтому я создаю заголовочный файл (protocol.h) со всеми моими сигнатурами функций и включаю protocol.h как из protocol.cpp, так и из main.cpp.

Но я получаю "множественное определение `flexcan_isr_can1()'" (это функция, определенная в библиотеке, на которую ссылаются, FlexCAN_T4). Я не могу понять, как избавиться от этой ошибки, и при этом все мои сигнатуры функций, константы и многое другое работают должным образом.

Примеры сообщений об ошибках (по одному для каждой функции, не относящейся к классу, определенной в FlexCan_T4.h):

.pio/build/teensy40/src/protocol.cpp.o: In function `flexcan_isr_can1()':
protocol.cpp:(.text._Z16flexcan_isr_can1v+0x0): multiple definition of `flexcan_isr_can1()'
.pio/build/teensy40/src/main.cpp.o:main.cpp:(.text._Z16flexcan_isr_can1v+0x0): first defined here
/Users/pdesrosiers/.platformio/packages/toolchain-gccarmnoneeabi/bin/../lib/gcc/arm-none-eabi/5.4.1/../../../../arm-none-eabi/bin/ld: Disabling relaxation: it will not work with multiple definitions

протокол.h

#pragma once
#include <FlexCAN_T4.h>
const uint8_t myConst = 100;
extern FlexCAN_T4<CAN1, RX_SIZE_256, TX_SIZE_16> flexCAN;

void myFunction();

протокол.cpp

#include "protocol.h"
FlexCAN_T4<CAN1, RX_SIZE_256, TX_SIZE_16> flexCAN;

void myFunction()
{
    //one of a hundred functions related to protocol, that should be defined outside of main.cpp.
    flexCan.doSomething(myConst);
}

main.cpp

#include "protocol.h"
#include <Arduino.h>

void setup()
{
  //some setup stuff...
}

void loop()
{
  myFunction();
}

В определенном смысле эти ошибки имеют смысл, так как протокол.h (и, транзитивно, FlexCAN_T4.h) многократно #included.

Но как я могу сохранить эту прекрасную организацию кода, которую мои обратные вызовы определяют вне main.cpp? Как правильно включить эти зависимости?


person roach374    schedule 30.09.2019    source источник
comment
Язык Arduino — это C++ с некоторыми функциями, а не C. Проблема в том, что в заголовочном файле <FlexCAN_T4.h> есть определение функции, но нет #pragma once   -  person Antti Haapala    schedule 30.09.2019
comment
@AnttiHaapala Поскольку FlexCAN_T4.h включается только транзитивно, через протокол.h, а протокол.h имеет #pragma один раз, разве этого не должно быть достаточно? (хотя я признаю, что #pragma не раз озадачивала меня более чем один раз, поскольку, похоже, никогда не делает то, что я думаю).   -  person roach374    schedule 07.10.2019


Ответы (3)


Если части, связанные с FlexCAN_T4, не нужны в протоколе.h, вы можете поместить их в файл cpp. Например, удалить следующую часть и поместить их в protocol.cpp:

включают

внешний FlexCAN_T4 flexCAN;

person Francis    schedule 30.09.2019
comment
#include ‹FlexCAN_T4.h› extern FlexCAN_T4‹CAN1, RX_SIZE_256, TX_SIZE_16› flexCAN; - person Francis; 30.09.2019
comment
Код, который я вставил, упрощен, чтобы проиллюстрировать минимальное воспроизведение. На самом деле, в protocol.h есть множество определений функций, которые, к сожалению, нуждаются в FlexCAN_T4 для своих параметров. - person roach374; 07.10.2019

Проблема в том, что flexcan_isr_can1 (и другие функции) определены в заголовочном файле, который включается в несколько единиц перевода. Это нарушение правила одного определения. В соответствующие определения функций следует добавить ключевое слово inline. им.


Это дефект библиотеки FlexCAN_T4; вы должны отправить вопрос сопровождающему библиотеки.

person Miles Budnek    schedule 30.09.2019
comment
Я являюсь автором библиотеки, и она все еще находится в разработке для функциональности оборудования. Аппаратное обеспечение вышло совсем недавно, так что все еще в процессе.. спасибо - person Antonio Brewer; 06.10.2019
comment
Поскольку FlexCAN_T4.h подключается только транзитивно, через protocol.h, который защищен #pragma один раз, не должно ли это остановить множественное включение? - person roach374; 07.10.2019
comment
@reach374 Нет. #pragma once или эквивалентные защитные элементы предотвращают включение заголовка более одного раза в одну и ту же единицу перевода. Проблема здесь в том, что FlexCAN_T4.h включен в несколько единиц трансляции (protocol.cpp и main.cpp). - person Miles Budnek; 07.10.2019

У меня уже есть включенные охранники, которые более рекомендуются, чем #pragma раз, и всегда были в H-файле:

#if !defined(_FLEXCAN_T4_H_)
#define _FLEXCAN_T4_H_

Где дефект, о котором вы говорите?

person Antonio Brewer    schedule 14.10.2019