#define and class definition under different file

Hi,

I get this sketch compiling :

#define PIN 3

class classTest {
  private:
  public:
    classTest() {
      uint8_t a = PIN;
    }
};

classTest test = classTest();

void setup() {
}

void loop() {
}

But, if i put the class definition under .h & .cpp file, i got an error :

#define PIN 3

#include "test.h"

classTest test = classTest();

void setup() {
}

void loop() {
}
`error: 'PIN' was not declared in this scope`

Looks like it's compiling first the .h before reading the .ino file.
Any idea how to use it ? I took a look at the MySensors library, and there is some #define before calling the class, so i hope it is possible.

Thx in advance,

Put that into test.h.

Hi,

It works but i want to create a library, so its not userfriendly to change define inside the librairie.
mysensors library have #define inside. Ino and no compilation problem. I don't understand how

Could you please explain in more detail which file is what and what exactly are you trying to achieve?

Can't you make constructor to which you pass the pin number the object should use?

I don't know if those are the right words, I'm not a C++ programmer. But my use of it through libraries seems to often do that kind of thing.

a7

You can't. It's how the Arduino build process works. Libraries are compiled on their own, and have NO knowledge of, or access to, ANY information in the .ino file.

Please explain your library file structure.

For a library the typical approach is a .h header file with all declarations and a .cpp implementation file. The header file is included with both the library and application .ino file.

If you want a user selectable pin number then you have to pass that number to the library e.g. in the constructor or begin() method.

It can works if a whole your lib is in the .h file and there is no .cpp file.

If pin is supposed to be a public member variable, the following should work:

// test.h
#pragma once
#include <Arduino.h>

class ClassTest {
public:
  uint8_t pin;
};
// project.ino
#include "test.h"

void setup() {
  Serial.begin(9600);
  
  ClassTest test {3};
  Serial.println(test.pin);  // Prints "3".
}

void loop() {}

Otherwise you could use a custom constructor as @alto777 and @DrDiettrich suggested.

// test.h
#pragma once
#include <Arduino.h>

class ClassTest {
public:
  ClassTest(uint8_t const);
  uint8_t getPin() const;
private:
  uint8_t pin_ {};
};
// test.cpp
#include "test.h"

ClassTest::ClassTest(uint8_t const pin) : pin_ {pin} {}

uint8_t ClassTest::getPin() const {
  return pin_;
}
// project.ino
#include "test.h"

void setup() {
  Serial.begin(9600);
  
  ClassTest test {3};
  Serial.println(test.getPin());  // Prints "3".
}

void loop() {}

Hi,

Thanks for the answers for u all. I can pass it on declaration, but i would like to not. I have like 10 parameters, and its more userfriendly to use #define and not to get them inside classTest call.
I understand how the compilation work, but i still dont understand how MySensors library do it.
For example :

#define MY_NODE_ID 123
#include <MySensors-Attiny.h>

MyMessage msg(sensorid, V_TRIPPED);

And if i look at the library, i can find "MY_NODE_ID" inside different file as MyTransport.cpp.

Any idea ? ^^

@b707 :
I think i will get your solution, will be faster for my implementation and not a big deal

Thanks for u all

Sorry, but it is impossible using it such way.

Please show the code of MySensors example that using such syntax

Look how plenty initialization parameters are handled in the SPI library as SPISettings. Defaults can be provided by the library and can be overwritten in user code before calling the constructor or begin() of a class, or by providing a different record whenever required.

Thx all for helping me

@b707 :
The MySensors library is a little bit to big to give example. But it's like

//parameter in .ino
#define MY_RFM69_CS_PIN 5

----- in MyConfig.h but it's supposed to define if not defined in .ino -----
#ifndef MY_RFM69_CS_PIN
#ifdef MY_RF69_SPI_CS
#warning MY_RF69_SPI_CS is depreciated, please use MY_RFM69_CS_PIN instead.
#define MY_RFM69_CS_PIN MY_RF69_SPI_CS
#else
#define MY_RFM69_CS_PIN DEFAULT_RFM69_CS_PIN
#endif
#endif

---------- in MyTransportRFM69.cpp -------
RFM69 _radio(MY_RFM69_CS_PIN, MY_RFM69_IRQ_PIN, MY_RFM69HW, MY_RFM69_IRQ_NUM);
uint8_t _address;

------------ in RFM69_new.cpp ----------

LOCAL void RFM69_csn(const bool level)
{
#if defined(__linux__)
	(void)level;
#else
	hwDigitalWrite(MY_RFM69_CS_PIN, level);
#endif
}


They are all called by an include "???.h"

I took a look at the SPI.cpp as mentionned by @DrDiettrich and there is SCK & MOSI which suppose to be #define somewhere. They are not in the .cpp or the .h
Maybe because the way the arduino compiler do it, its been already defined and include as it was inside ?

    pinMode(SCK, OUTPUT);
    pinMode(MOSI, OUTPUT);

Is there a difference beetween including .h from the .ino file directory and including .h from the library directory ?
Or it makes no difference for the compiler ?

@Delta_G I got this one, there is plenty way to do it. Actually the best & easyfriendly solution is to remove the .ccp and put everything inside the .h

where this config.h file should be located - in the library dir or in the sketch dir?

@Delta_G
I understand your point of view :blush:
I'm not here to make the next big library of adruino, only one for me and eventually on a git so other people can use it.

For me, and only for arduino/esp, its more easy to have something like :

#define LIBRARY_PARAM1 a
#define LIBRARY_PARAM2 b
#define LIBRARY_PARAM3 c

classTest test();

than

#define LIBRARY_PARAM1 a
#define LIBRARY_PARAM2 b
#define LIBRARY_PARAM3 c

classTest test(LIBRARY_PARAM1, LIBRARY_PARAM2, LIBRARY_PARAM3);

------ or -----------
classTest test(a, b, c);

It's also more easy for me, i only need to have one test(){} :rofl:

I think if the sketch dir is in the compiler include path during the library compilation - we can put config.h in the sketch dir and it would be a solution for the topic main problem.

I understand :slight_smile:
I was only asking in relation to OP's question

the simplest is not always the best

what's next? will you use this LIBRARY_PARAM1 in the library sourcecode every time you need this parameter?

Let's go from the other end - I hope you understand why you shouldn't use pin numbers directly in the code, like this

digitalWrite(13, LOW);

So, your "simple way" is practically the same. Anyone who wants to change the description of your parameters will have to find all the places where they occur in the code and change them

As i said, i understand ur point of view, but as i said too, in my case, its more easy that way. I'm not here to argue about what is the best or not the best.

If you can explain me how the spi libray do to have external #define inside the class definition, it will be nice :slight_smile: