c++visual-studio-codearduinoplatformiomultiple-definition-error

Platformio C++ multiple "multiple definition of"


I can't resolve this problem on my arduino project. I am using Platformio on vscode.

I want to use the MFRC522_I2C library to read rfid badges so I created a class to use the libraries methods.

The library can be found here: https://github.com/arozcan/MFRC522-I2C-Library

Here is my code:

main.cpp:

#include <Arduino.h>
#include "rfid/Rfid.hpp" // my rfid class

Rfid _rfid;
void setup()
{
    Serial.begin(115200);
    _rfid.setupRfid();
}

void loop()
{
    _rfid.rfidLoop();
}

Rfid.cpp:

#include "Rfid.hpp"

Rfid::Rfid(/* args */)
{
}

Rfid::~Rfid()
{
}

void Rfid::setupRfid()
{
  _rfidReader.PCD_Init();
}

void Rfid::rfidLoop()
{
    // here is my code to read the rfid
}

Rfid.hpp:


#ifndef _RFID_HPP_
#define _RFID_HPP_

#include "../lib/rfidReader/MFRC522_I2C.h" // the MFRC522 library

MFRC522 _rfidReader(0x28);

class Rfid
{
private:
  /* data */
public:
  Rfid(/* args */);
  ~Rfid();
  void setupRfid();
  void rfidLoop();
};

#endif

I got this error:

multiple definition of `_rfidReader'; .pio/build/m5stack-core2/src/main.cpp.o:[PATH]/src/rfid/Rfid.hpp:7: first defined here

What am I missing here?

Thanks!


Solution

  • The statement

    MFRC522 _rfidReader(0x28);
    

    is a definition of a variable. You can have only one single definition for each variable in your program.

    Because you include the header file in two source files, it will be defined twice, once in each source file.

    To solve your problem, declare the variable in the header file:

    extern MFRC522 _rfidReader;
    

    Then move the definition into a single source file.


    Good things to learn related to this issue:


    After checking the code some more it seems that the _rfidReader variable really should be a member variable of the Rfid class.

    Then your header file would look like this instead:

    #ifndef _RFID_HPP_
    #define _RFID_HPP_
    
    #include "../lib/rfidReader/MFRC522_I2C.h" // the MFRC522 library
    
    class Rfid
    {
    private:
      /* data */
      MFRC522 _rfidReader;
    public:
      Rfid(/* args */);
      ~Rfid();
      void setupRfid();
      void rfidLoop();
    };
    
    #endif
    

    And in the source file the constructor should look like this:

    Rfid::Rfid(/* args */)
      : _rfidReader(0x28)  // Initialize the member object
    {
    }