#define problem!

I think i don't understand #define as i should! I am trying to make a library for my devices! Lot of them use same parts of code and some other parts are different!

What i am trying to do, is in my .ino file, i include a file callled GHS400.h who is the base configuration file for this specific device.

the top of this file look like this:

#ifndef _GHS400_h
#define _GHS400_h
#include "EraIoTBase.h"
#include "setpoints.h"
#include <SerialTransfer.h>
#include <ArduinoJson.h>
const char device[] = "0704";
#endif

so in this file i #define _GHS400_h,

Inside the file setpoints.cpp i include the file setpoints.h

and inside this .cpp file i try to detect if _GHS400_h is defined or any other device i use to let it compile only the part of the code that is different for those device but i never get the define even if i know i it is defined! I was pretty shure that the #define where pre processed!

So there is clearly something i don't understand at all!

Is there any good way to do what i try to do?

Thanx a lot!

Just some ideas:

  1. #defines have to be checked by #ifdef, e.g. #ifdef _GHS400_h

  2. Do a simple test within setpoints.cpp which is including GHS400.h:

#include "GHS400.h"
...

#ifdef _GHS400_h
Serial.println("_GHS400_h is defined");
#endif

If the compiler found all included header files and compilation is successful you should see the printed text on the Serial Monitor.

If _GHS400_H is not defined in setpoints.h, how should it be known in setpoints.cpp if this includes only setpoints.h?
Or do you include GHS400.h in setpoints.cpp?

No i don't inlcude GHS400.h in setpoint but setpoints.h in GHS400.h

That's of no relevance when compiling setpoints.cpp. When compiling setpoints.cpp the (pre)compiler sees only defines that are defined in setpoints.cpp or in included .h files. Wether these .h files are also included in other files does not matter.

Ok! I was thinking that the compiler was scanning for all #define prior to compiling so that all of them are available!! So if i understand well ,there is no way to know if a library as been loaded from another file?

Thanx!

Every .cpp file is compiled separately and the (pre)compiler sees only what is included in that .cpp. Of course it also sees nested includes - .h files may include additionally other .h files. But wether the .h files are also included elsewhere is not seen.

The precompiler is not 'scanning' for all #defines. A #define is only valid starting from the line in which it appears.

1 Like

They can also be checked if #ifndef - as in the OP

  • #ifdef checks if something is defined;
  • #ifndef checks if something is not defined.

You can also do #if defined() and #if !defined() - potential advantages:

  • can test multiple things;
  • can take a #else clause.

I doubt you are right on this because if you are it implies that a same piece of code can be included multiple time by multiple files. This is the reason they check with #ifdef _LIBRARY... before re declaring all variable.

There is really something there i don't understand!

Which point are you doubting?
Including one .h file several times in the same compiler run may easily occur with nested includes. And depending on the content of the .h file this may be a problem. This is why the includes are usually secured against compiled twice.

1 Like

Yes, it can be - the so-called "include guards" are there to make sure that this causes no problems!

edit

specifically, they are for when the same header gets included multiple times in the same file - eg, via nested includes.

The check of #ifdef _LIBRARY... does work only inside a current compiling unit - for example in the current .cpp file. This check doesn't prevent multiple inclusions of the same header to the multiple .cpp files.
It is why you must not, as a rule, put the variables in the .h files, as here:

because multiple inclusion of this header in different files will lead to a ā€œmultiple variable definitionā€ error during compilation

1 Like

Indeed.

A common example would be things like stdint.h and stdbool.h

You should not put variable definitions in a .h file. That will cause multiple definition linker errors if that .h is included in more than one .cpp file (or in the .ino file and another .cpp file). Same is true for regular function definitions. Member functions within a class definition and template functions are a slightly different store.

See My Post #5 in this Thread for a basic guide to improving code modularity by breaking it into .h / .cpp files.

1 Like

GHS400.h:

#ifndef _GHS400_h
#define _GHS400_h

#include "EraIoTBase.h"
#include "setpoints.h"
#include <SerialTransfer.h>
#include <ArduinoJson.h>

const char device[] = "0704";

#endif

setpoints.h:

#ifndef _SETP_H
#define _SETP_H

// Define the _SETP_H macro to indicate we're in setpoints.h
#define _SETP_H

// Other declarations common to all devices
void commonFunction();

#ifdef _GHS400_h
// Define specific functions or variables for GHS400
void ghs400Function();
#endif

#endif

setpoints.cpp:

#include "setpoints.h"

// Define the common function
void commonFunction() {
    // Common code for all devices
}

#ifdef _GHS400_h
// Define the GHS400-specific function
void ghs400Function() {
    // Code specific to GHS400
}
#endif

Your .ino file:

#include "GHS400.h"
#include "setpoints.h"

void setup() {
    // Your setup code
}

void loop() {
    // Your loop code

    // Call common function
    commonFunction();

#ifdef _GHS400_h
    // Call GHS400-specific function
    ghs400Function();
#endif
}

Explanation of the fixes:

  1. Define in setpoints.h: In your setpoints.h, we define a macro _SETP_H to indicate that we are in the setpoints.h file. This helps ensure that the file is included only once.

  2. Include order: Make sure to include "GHS400.h" before "setpoints.h" in your .ino file to ensure that _GHS400_h is defined before you try to use it in "setpoints.cpp."

  3. Common and Specific Functions: We've created a common function, commonFunction(), that can be used by all devices. For GHS400, we have ghs400Function() as a specific function. These functions are defined in "setpoints.cpp" and called in your .ino file.

  4. Conditional Compilation: The conditional compilation checks whether _GHS400_h is defined and, if so, includes or excludes the code specific to the GHS400. This way, you can have device-specific code sections in "setpoints.cpp" that are only compiled when _GHS400_h is defined.

By following these fixes, you should be able to conditionally compile code for different devices by defining _GHS400_h in "GHS400.h" or another device-specific header.

This will not work because setpoints.cpp does not include GHS400.h. So setpoints.cpp doesn't know anything about #defines in GHS400.h

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.