0

I'm writing an Arduino app (Using platformIO in VSCode), and including an external CAN library (FlexCAN_T4). I want to define all of my protocol / message handler callbacks in a separate file (protocol.cpp), and refer to them from my main file (main.cpp). So I create a header file (protocol.h) with all my function signatures, and include protocol.h from both protocol.cpp and main.cpp.

But I'm getting "multiple definition of `flexcan_isr_can1()'" (which is a function defined in a referenced library, FlexCAN_T4). I can't figure out how to get rid of this error, and still have all my function signatures and constants and whatnot work properly.

Sample error messages (one for each non-class function defined in 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

protocol.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();

protocol.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();
}

In a certain sense, these errors make sense, since protocol.h (and, transitively, FlexCAN_T4.h) is being #included multiple times.

But how can I keep this nice organization of code, which my callbacks defined outside main.cpp? What's the correct way to include these dependencies?

roach374
  • 61
  • 1
  • 6
  • The Arduino language is C++ minus some features, not C. The problem is that the header file `` has a function **definition** but it doesn't have `#pragma once` – Antti Haapala -- Слава Україні Sep 30 '19 at 04:31
  • @AnttiHaapala Since FlexCAN_T4.h is only included transitively, via protocol.h, and protocol.h has #pragma once, shouldn't that be enough? (though I admit, #pragma once has mystified me on more than one occasion, as it never seems to do what I think it will). – roach374 Oct 07 '19 at 02:14

3 Answers3

0

If FlexCAN_T4 related parts are not necessary in protocol.h, you may put them in cpp file. Such as removing the following part and put them to protocol.cpp:

include

extern FlexCAN_T4 flexCAN;

Francis
  • 1
  • 2
  • #include extern FlexCAN_T4 flexCAN; – Francis Sep 30 '19 at 04:42
  • The code I pasted is simplified to illustrate a minimal repro. In reality, there are a ton f function definitions in protocol.h, that need FlexCAN_T4 for their parameters unfortunately. – roach374 Oct 07 '19 at 02:21
0

The problem is that flexcan_isr_can1 (and other functions) is defined in a header file that gets included into multiple translation units. This is a violation of the One Definition Rule. The relevant function definitions should have the inline keyword added to them.


This is a defect in the FlexCAN_T4 library; you should submit the issue to the library's maintainer.

Miles Budnek
  • 28,216
  • 2
  • 35
  • 52
  • I am the author of the library and it is still in development for functionality of the hardware. The hardware just came out recently so things are still in process.. thanks – Antonio Brewer Oct 06 '19 at 07:15
  • Since' FlexCAN_T4.h is only included transitively, via protocol.h, which is "protected" by #pragma once, shouldn't that stop a multi-include? – roach374 Oct 07 '19 at 02:17
  • @roach374 No. `#pragma once` or equivalent include guards stop a header from being included more than once in _the same translation unit_. The issue here is that FlexCAN_T4.h is included in multiple translation units (protocol.cpp and main.cpp). – Miles Budnek Oct 07 '19 at 04:06
0

I already have include guards, which are more recommended than #pragma once, and was always in the H file:

#if !defined(_FLEXCAN_T4_H_)
#define _FLEXCAN_T4_H_

Where is the defect you claim to be seeing?