2

I'm creating an Arduino library and have 3 files - a "test.ino" program, and two library/class files: "testLibrary.h" and a "testLibrary.cpp".

The library makes use of some hardware-specific resources such as registers and ISRs that depend upon which I/O pin is used, and this should be done at compile time.

I would like to #define a pin number in the main program which, at compile time, is used in the library to determine which code sections are activated. Since this will be a standard Arduino library for use by others, it should compile and run without users having to change their compiler or #include path to make it work.

But it seems that the scope of #define in the main program/sketch does not extend to the library.

test.ino

#define PIN_NUMBER 3
#include "testLibrary.h"
void setup() {}
void loop() {}

testLibrary.h

#ifndef _TESTLIBRARY_h
#define _TESTLIBRARY_h
#ifndef PIN_NUMBER
#error PIN is not defined
#endif
class test {
public:
  test();
  ~test();
};
#endif

testLibrary.cpp

#include "testLibrary.h"
test::test(){}*
test::~test(){}

Compiling the above branches to "#error" using the Arduino IDE 1.8.13 and also using Visual Studio with Visual Micro.

Is there a way for me to have an Arduino library use a "#define" from the main sketch?

9
  • You actually didn't define PIN_NUMBER in your code. Or is that a copy&paste error?
    – chrisl
    Commented Feb 9, 2021 at 7:18
  • You have two #endif but only one #if in testLibrary.h. This will cause a compilation error if you define PIN_NUMBER in your main code (test.ino) when it skips the #error in testLibrary.h. Maybe you did not notice the #endif without #if error? You can fix it by inserting #define _TESTLIBRARY_h as the first line of testLibrary.h. I.o.w. the scope of PIN_NUMBER will be global if you define it in test.ino. Try it.
    – StarCat
    Commented Feb 9, 2021 at 7:54
  • It was indeed a copy-and-paste error, I put the first line of my code on the same line as the code-tags which meants that for each of my code snippets the first lines were missing. I've corrected that (@chrisl & StarCat)
    – Zanshin
    Commented Feb 9, 2021 at 9:30
  • You can use a library header file in more than one other libraries or applications. So the library header files should not be dependend on where they were used. Even if the preprocessor would allow defined local macros in included (header) files, it would be a very bad design. How can you know what the main app will do? That leads to horror errors for people using your lib. If you need the value in the class, just add a property to the class and set it in the main code by your constant. The SoftwareSerial library does that to define the tx and rx pins for example. Commented Feb 9, 2021 at 9:51
  • 4
    Is there a special reason, why you want to use a define? The convention is to let the user provide such information as parameters for either the class constructor or the begin() method.
    – chrisl
    Commented Feb 9, 2021 at 11:14

1 Answer 1

2

The scope of a #DEFINE macro is the translation unit. That is the current .c or .cpp file that is currently being compiled.

In you code PIN_NUMBER is defined in test.ino. The #include macro literaly copies the content of testLibrary.h into test.ino. So for the compiler this is working perfectly fine as PIN_NUMBER is defined.

Your testLibrary.cpp however is not happy with that. Including testLibrary.h for compilation lacks the definition of PIN_NUMBER.

The Arduino IDE is very limited and does not offer you a way to define PIN_NUMBER globally. This is usually done with the compiler argument -DPIN_NUMBER=3. All translation units will get this argument and thus the compilation would succeed. No need to define PIN_NUMBER in code.

2
  • Unfortunately adding a compiler argument is not a solution - the whole problem setting was due to attempting to make a standard library which any Arduino IDE user could simply download and include without having to make any subsequent changes.
    – Zanshin
    Commented Feb 10, 2021 at 7:35
  • In the answer to a similar question it’s suggested to put the #define in a header file that is then included into all the translation units (i.e., ino, c or cpp files) arduino.stackexchange.com/questions/23681/…
    – RowanP
    Commented Mar 6, 2022 at 13:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.