Recursive inclusion

Hello everyone,
I have a problem with including one library in another and conversely, if I use #include in both I generate a recursion and it doesn’t work.
I have tried declaring class Can; (as you can see below) but I get the error that it can’t find the file mac.h

If I use only the can library (can.h and can.cpp) everything works and the lib mac.h also finds it and works

FILE CAN.H

#ifndef CAN_H
#define CAN_H

#include "mb.h"
#include "mac.h"

class Can {
public:
    Can(Mb *mb);
    void useMacLib();
    void useMb();
private:
   Mb *_mb;
};
#endif

FILE CAN.CPP

#include "can.h"

Can::Can(Mb *mb){
   _mb = mb;
}

void Can::useMacLib(){
    refreshMacAddress();
}

void Can::useMb(){
   _mb->updateLib();
}

FILE MB.H

#ifndef MB_H
#define MB_H

#include "mbController.h"
class Can;

class Mb {
public:
    Mb();
    void setCan(Can *can);
    void useCan();
    void useMb();
private:
    Can *can;
};
#endif

FILE MB.CPP

#include "mb.h"
#include "can.h"

Mb:Mb(){}

void Mb::setCan(Can *can){
   _can = can
}

void Mb::useCan(){
   _can->blockCanRequest();
}

void Mb::useMb(){
   mbControllerExampleFunction();
}

Where and what is mac.h?

Regarding to can.h, can.cpp should have the implementation… but it’s empty, except for the include !?

What is xxxx.h ?

Again an “empty” .cpp file ?

The examples do not seem to be complete…
What are you trying to achieve?

This should work works:

can.h
#pragma once

class Mb;

class Can {
  public:
    Can(Mb* mb);

  private:
    Mb* mb;
};
can.cpp
#include "can.h"

#include "mb.h"

Can::Can(Mb *mb)
    : mb(mb) {
}
mb.h
#pragma once

class Can;

class Mb {
  public:
    Mb();
    void setCan(Can *can);
    void useCan();
  private:
    Can *can;
};
mb.cpp
#include "mb.h"

#include "can.h"

Mb::Mb() {}

void Mb::setCan(Can *can) {
    this->can = can;
};

void Mb::useCan() {
    
}

The “can.h” only contains a forward declaration of Mb.
This is sufficient so that an Mb* can be used in the declaration of Can.

In the “can.cpp” the “mb.h” can then be included in order to access the functions of Mb.

Exactly the same the other way around:

The “mb.h” contains a forward declaration of Can.
This is sufficient so that a Can* can be used in the declaration of Mb.

The “can.h” can then be included in the “mb.cpp” to access the functions of Can.

I have updated the code above, I had voluntarily omitted parts so as not to make it too complex, but I had actually omitted too much for it to be readable.
In the meantime I saw your solution, I had also tried this way of putting the class declarations inverted for both files but I always get that the mac.h library does not exist
lib/Can/src/Can.h:12:10: fatal error: Mac.h: No such file or directory
I also have other libraries included before and those don’t give me any problems just as they don’t give me problems if I just use the can library obviously removing any reference to the mb library

What is the Mac.h? Where does it come from?

Does the Mac.h even exist?
So the problem seems to be more the Mac.h…

I tried editing the code by only putting class declarations as suggested in your code but unfortunately I also have custom structures in mb.h before the actual class declaration and if mb.h is not actually included in can.h these are not seen.
So I tried putting these structures in a separate file mbStruct.h and this included in both mb.h and can.h.
Now the problem that does not include me mac.h has moved to mbStruct.h this I think because it is the last one I put in and once I have solved this I will also get the mac.h insertion error again
I hope I have illustrated the steps well

:+1:

There are still questions about “Mac.h”.
Where is the file and where does it come from?
Is it your own source code file?

This is the complete code for Mac (MacAddress)
I had previously called it just Mac to simplify

The implementation file has nothing special except the actual code…

#ifndef MacAddress_h
#define MacAddress_h
#include <string>
#include <sstream>
#include <iomanip>
#include "esp_mac.h"

class MacAddress
{
public:
    static uint8_t *getMacAddress_uint8();
    static std::string getMacAddress_str();
    static uint64_t getMacAddress_uint64();
private:
    static void initialize();
    static uint8_t mac[6];
    static bool initialized;
};

#endif

So where are Mac.h & Mac.cpp located?
Please show the file and folder structure of your project!

lib/MacAddress/src/MacAddress.h
lib/MacAddress/src/MacAddress.cpp

lib/Can/src/Can.h
lib/Can/src/Can.cpp

lib/Mb/src/Mb.h
lib/Mb/src/Mb.cpp

include/MbStruct.h

What’s the content of include/MbStruct.h ? (where the error happens now)

There are only:

#pragma once
#include ‘esp_bit_defs.h’
#include ‘stdint.h’

  • 4 enum
  • 4 struct

I don’t think libraries located in /lib have access to files located in /include.
Usually only the project itself have access to files located in /include.

Please post the error log.

esptool.py v4.5.1
Creating esp32s3 image...
Merged 1 ELF section
Successfully created esp32s3 image.
In file included from lib/Can/src/Can.cpp:1:
lib/Can/src/Can.h:16:10: fatal error: Mb.h: No such file or directory

****************MbStruct.h dependency? Check our library registry!
*
* CLI  > platformio lib search "header:MbStruct.h"
* Web  > https://registry.platformio.org/search?q=header:MbStruct.h
*
****************************************************************************

   16 | #include "MbStruct.h"
      |          ^~~~~~~~~~~~~~~~~~~~~~
compilation terminated.

What do you advise me to do? Do I put the MbStruct.h file in
lib/MbStruct/src/MbStruct.h ?

Give it a try.

Can is not able to see MbStruct, because MbStruct is in located /include.

Only source files of the project itself have access to files located in /include

I have tried it and so I no longer get the error in MbStruct, but the error in MacAddress.h has returned.

In file included from lib/Mb/src/Mb.cpp:2:
lib/Can/src/Can.h:12:10: fatal error: MacAddress.h: No such file or directory

********************************************************************
* Looking for MacAddress.h dependency? Check our library registry!
*
* CLI  > platformio lib search "header:MacAddress.h"
* Web  > https://registry.platformio.org/search?q=header:MacAddress.h
*
********************************************************************

   12 | #include "MacAddress.h"
      |          ^~~~~~~~~~~~~~
compilation terminated.

What I don’t understand is that MacAddress.h is included twice as can.h I include it from both can.cpp and mb.cpp and this generates an error when I include it the second time (from mb.cpp)

I solved this by declaring class MacAddress; inside can.h and including MacAddress.h in can.cpp

Thank you very much for the valuable support!

1 Like