I have the following problem:
I'm writing a collection library for a bunch of sensors to be used with a microcontroller. Meaning I take a lot of libraries for sensors and abstract and simplify them a bit in a unified library for a student project.
I use #define structures to figure out which sensors the students want to use and connected.
Example:
#define IR_SENSOR_USED
In the .h and .cpp files of the library I then use #ifdef-#endif pairs to define and declare the functions for the given sensor as well as include the given libraries.
Example from my Sensors.h file:
#ifdef IR_SENSOR_USED
#include "SparkFun_GridEYE_AMG88/src/SparkFun_GridEYE_Arduino_Library.h"
extern GridEYE grideye;
void setup_ir_sensor();
void read_ir_sensor();
void enable_ir_interrupt(float lower, float upper, float hysteresis);
void disable_ir_interrupt();
#endif
and from my Sensors.cpp file:
#ifdef IR_SENSOR_USED
void setup_ir_sensor() {
Wire.begin(16, 17, 0x69);
grideye.begin(0x69, Wire);
}
void read_ir_sensor() {
for (int i = 0; i <= 64; i++) {
sensor_values.ir_pixel_temp[i] = grideye.getPixelTemperature(i);
}
sensor_values.ir_device_temp = grideye.getDeviceTemperature();
}
void enable_ir_interrupt(float lower, float upper, float hysteresis) {...}
void disable_ir_interrupt() {...}
#endif
However, so long as I have the #ifdef in the .cpp file, I get the following error if I try to call the function in the setup():
sketch/Sensors.ino.cpp.o:(.literal._Z5setupv+0xc): undefined reference to `read_ir_sensor()'
sketch/Sensors.ino.cpp.o: In function `setup()':
.../Sensors/Sensors.ino:112: undefined reference to `read_ir_sensor()'
collect2: error: ld returned 1 exit status
exit status 1
If I comment them out, the code executes fine. Another function (setup_sensors()), which is also in the Sensors.h and .cpp files and is not surrounded by an #ifdef works also fine.
This is my Sensors.ino sketch:
#define IR_SENSOR_USED
//#define COLOR_SENSOR_USED
//#define ENV_SENSOR_USED
//#define TEMP_SENSOR_USED
#include "Sensors.h"
void setup() {
sensor_setup();
read_ir_sensor();
}
void loop() {
}
What's the reason for this? (Why) does the preprocessor not execute the directives in the .cpp file properly?
As the comments and other answer pointed out, any #define directives are only visible in the files that contain them. So having
#define IR_SENSOR_USED
in Sensors.cpp won't affect any code that's not compiled in Sensors.cpp (importantly, it will affect code that's contained in .h files that are included in Sensors.cpp after the #define. But it wouldn't affect anything contained in a different .cpp file.
More sophisticated build environments than Arduino have better and more complicated ways to deal with this problem, but the Arduino world doesn't give you a lot of tools to handle this.
What I do in the Arduino world is simply have a file called config.h which contains all the #define statements that I need project-wide. I #include "config.h" in each file that needs these values.
So in your case, you'd put your all the defines that show which devices are used in config.h and then #include "config.h" at the start of every file that depends on it.
You could even include it at the start of your Sensors.h file. I'd consider keeping the two files separate so that there would be a clear boundary between the stuff that needs to be configured and the stuff that's useful code.
I also keep any sensitive values (wifi credentials, passwords, API keys) in this file, and exclude it from code I publish on Github. In its place I include a "config-example.h" file with all the directives in it but with dummy values, so that others using the code can edit and rename it.
This question might be an instance of an XY problem.
If you would like the users of library to pick the functionality they need it would make more sense to put declarations in separate headers. E.g., IR_sensor.h and then
#define IR_SENSOR_USED
#include "Sensors.h"
becomes just #include "IR_sensor.h".
If the size of the library is or concern, splitting it into separate libraries is an option.
The third option is to provide the functionality as a header-only library.
Exact answer:
What's the reason for this? (Why) does the preprocessor not execute
the directives in the .cpp file properly?
The most likely reason is that Sensors.cpp is unaware of #define IR_SENSOR_USED. Define is in another file that is not included.
However even if IR_SENSOR_USED would be defined in the Sensors.cpp another problem arises: re-compilation of Sensors.cpp for every possible combination of defines is necessary. Otherwise the ifdefed-code is excluded from compilation and can't be simply enabled on the client side by calling #define.
Related
I'm writing a BLE library for Arduino (and potentially other platforms) that needs slightly different versions of the code based on the underlying hardware.
What I'd like to do is put the platform specific code in a sub-folder called "Variants" and then use #IFDEFS in the main header file to point to the file it needs, but no matter what I do, I can't seem to get the compiler to "find" any code in a subfolder. I'm using Platformio on Atom as my IDE, but I suspect this is an Arduino, not an IDE issue.
/BleStar.h
// Header file BleStar.h - the main Arduino code does a #include "BleStar.h" which works fine
#ifndef BleStar_h
#define BleStar_h
if defined(BLE_DEVICE_ADAFRUIT_NRF52)
#include "Bluefruit.h" // The Adafruit Bluefruit library for NRF52 chipsets
#include "Variants/AdafruitNRF52.h" // The NRF52 specific code that I wrote
#elif define(BLE_DEVICE_ADAFRUIT_NRF51)
#include "Adafruit_BluefruitLE_SPI.h" // The Adafruit Bluefruit library for NRF51 chipsets
#include "Adafruit_BLE.h"
#include "Variants/AdafruitNRF51.h" // The NRF51 specific code that I wrote
#endif
class BleStar {
public:
...
// Declarations here for the hardware specific code that shows up in "Variants/AdafruitNRF51.h" etc.
int write(uint8_t u);
uint8_t read();
boolean available();
...
private:
};
/Variants/AdafruitNRF52.h
#ifndef AdafruitNRF52_h
#define AdafruitNRF52_h
#include "BleStar.h"
// nothing in here - declarations are in BleStar.h as part of the class declaration, and AFAIK you can't split a class declaration across multiple headers
#endif
/Variants/AdafruitNRF52.cpp
#ifndef AdafruitNRF52_cpp
#define AdafruitNRF52_cpp
#include "BleStar.h" // shouldn't hurt to repeat it
#include "AdafruitNRF52.h"
int BleStar::write(uint8_t u) {
//nrf52 specific code
}
uint8_t BleStar::read() {
// more nrf52 specific code
}
// etc.
#endif
What doesn't work:
The above. Using a #include AdafruitNRF52.h in BleStar.h when AdafruitNRF52.h is in a subdirectory. I get an undefined reference to `BleStar::write(uint8_t)' error, so the compiler can't "see" the .cpp file
using "#include AdafruitNRF52.cpp" at the bottom of BleStar.h (i.e. after all the declarations) and commenting out AdafruitNRF52.h completely. I get a large number of compile errors like "multiple definitions of ...." despite Adafruit.cpp having header guards (and yes i know you are not supposed to include .cpp files, but i'm trying stuff)
What does work:
Putting AdafruitNRF52.cpp in the main library directory surrounded by IF defined (BLE_DEVICE_ADAFRUIT_NRF52) /// #endifs. It works, but then the main directory will get very crowded when I add more hardware types
Putting separate classes in subfolders that have .h and .cpp files. They compile fine. I don't want to make a sub-class for this if I can avoid it, however.
Anyone know how to force compilation of code in library sub-folders? I'm getting pretty stuck
I was wondering if there is an elegant way to solve this problem. Suppose there's a common header eg
// common.h
#ifndef COMMON_H
#define COMMON_H
#define ENABLE_SOMETHING
//#define ENABLE_SOMETHING_ELSE
#define ENABLE_WHATEVER
// many others
#endif
Now this file is included by, let's say 100 other header files and the various #define are used to enable or disable some parts of code which are confined to just 1-2 files.
Everytime a single #define is changed the whole project seems to be rebuilt (I'm working on Xcode 5.1), which makes sense as it must be literally replaced all around the code and the compiler can't know a priori where it's used.
I'm trying to find a better way to manage this, to avoid long compilation times, as these defines are indeed changed many times. Splitting each define in their corresponding file/files could be a solution but I'd like the practical way to have everything packed together.
So I was wondering if there is a pattern which is usually used to solve this problem, I was thinking about having
// common.h
class Enables
{
static const bool feature;
};
// common..cpp
bool Enables::feature = false;
Will this be semantically equivalent when compiling optimized binary? (eg. code inside false enables will totally disappear).
You have two distinct problems here:
Splitting each define in their corresponding file/files could be a solution but I'd like the practical way to have everything packed together.
This is your first problem. If I undestand correctly, if you have more than one functional area, you are not interested in having to include a header for each of them (but a single header for everything).
Apply these steps:
do split the code by functionality, into different headers; Each header should contain (at most) what was enabled by a single #define FEATURESET (and be completely agnostic to the existence of the FEATURESET macro).
ensure each header is only compiled once (add #pragma once at the beginning of each feature header file)
add a convenience header file that performs #if or #ifdef based on your defined features, and includes the feature files as required:
// parsers.h
// this shouldn't be here: #pragma once
#ifdef PARSEQUUX_SAFE
#include <QuuxSafe.h>
#elif defined PARSEQUUX_FAST
#include <QuuxFast.h>
#else
#include <QuuxSafe.h>
#endif
// eventually configure static/global class factory here
// see explanation below for mentions of class factory
Client code:
#include <parsers.h> // use default Quux parser
#define PARSEQUUX_SAFE
#include <parsers.h> // use safe (but slower) Quux parser
So I was wondering if there is a pattern which is usually used to solve this problem
This is your second problem.
The canonical way to enable functionality by feature in C++, is to define feature API, in terms of base classes, class factories and programming to a generic interface.
// common.h
#pragma once
#include <Quux.h> // base Quux class
struct QuuxFactory
{
enum QuuxType { Simple, Feathered };
static std::unique_ptr<Quux> CreateQuux(int arg);
static QuuxType type;
};
// common.cpp:
#include <common.h>
#include <SimpleQuux.h> // SimpleQuux: public Quux
#include <FeatheredQuux.h> // FeatheredQuux: public Quux
std::unique_ptr<Quux> QuuxFactory::CreateQuux(int arg)
{
switch(type) {
case Simple:
return std::unique_ptr<Quux>{new SimpleQuux{arg}};
case Feathered:
return std::unique_ptr<Quux>{new FeatheredQuux{arg}};
};
// TODO: handle errors
}
Client code:
// configure behavior:
QuuxFactory::type = QuuxFactory::FeatheredQuux;
// ...
auto quux = QuuxFactory::CreateQuux(10); // creates a FeatheredQuux in this case
This has the following advantages:
it is straightforward and uses no macros
it is reusable
it provides an adequate level of abstraction
it uses no macros (as in "at all")
the actual implementations of the hypothetical Quux functionality are only included in one file (as an implementation detail, compiled only once). You can include common.h wherever you want and it will not include SimpleQuux.h and FeatheredQuux.h at all.
As a generic guideline, you should write your code, such that it requires no macros to run. If you do, you will find that any macros you want to add over it, are trivial to add. If instead you rely on macros from the start to define your API, the code will be unusable (or close to unusable) without them.
There is a way to split defines but still use one central configuration header.
main_config.h (it must not have an include guard or #pragma once, because that would cause strange results if main_config.h is included more than once in one compilation unit):
#ifdef USES_SOMETHING
#include "something_config.h"
#endif
#ifdef USES_WHATEVER
#include "whatever_config.h"
#endif
something_config.h (must not have include guards for the same reason as main_config.h):
#define ENABLE_SOMETHING
All source and header files would #include only main_config.h, but before the include they must declare what part of it would they be referring to:
some_source.cpp:
#define USES_SOMETHING
#include "main_config.h"
some_other_file.h:
#define USES_WHATEVER
#include "main_config.h"
I have some class for specific debug purposes, so I use it only when interested in given functionality
to prevent source rubbish when not needed, I tried to handle it by preprocessor,
so the structure is something like this:
===main.cpp===
#define nowUseTmp
#include "tmp.h"
/*normal code which accesses tmp via macros*/
===EOF===
===tmp.h===
#ifdef nowUseTmp
/* class declaration */
/* macros to use static methods on class*/
#else
/*empty macro variants, so they may freely stay in code where needed*/
#endif
===EOF===
===tmp.cpp===
/*EXPECTED PLACE OF PROBLEM*/
#ifdef nowUseTmp
/* definitions */
#endif
===EOF===
problem is, that when I enable nowUseTmp (before the_very_first/each include), linker reports unresolved external (like if the macro was defined in header and NOT defined in the cpp file)
Question:
Why / How / What is better approach
I expect that cpp files are translated individually, without knowledge of include chain (thus cannot have info about the define)
Is that the case?
If so, how to workaround, so I can have constant "tmp.*" files between multiple projects, and manage enabled/disabled individually per project (i.e. not to use define inside relevant header)
Just to clarify
->when I place "#define tmpUseNow" inside relevant header (tmp.h), all works fine
->relevant header (tmp.h) is included from relevant definition file (tmp.cpp)
->same behavior tested with simplified project with only three files as in example
-> relevant files (tmp.h, tmp.cpp) are assumed constant files shared between many projects (so I do not see how to order them to include predetermined third file with definitions, which would be individual for projects that use them)
Yes, each cpp file is processed independently. If I were you, I'd make sure to include tmp.h in tmp.cpp, and I'd only ever define nowUseTmp in tmp.h.
You can add to your tmp.cpp functions (name it use_tmp) additional parameter with default value = nowUseTmp and examine it value for particular behavior:
tmp.h :
/* takes par2 value from the define */
void use_tmp(int par1, int par2 = nowUseTmp);
tmp.cpp :
void use_tmp(int par1, int par2)
{
if(!par2) /*do smth*/ return;
}
Is the #include <file> meant to be used for headers only or is it simply a mechanical "inject this code here" that can be used anywhere in the code?
What if I use it in the middle of a cpp function to just "inject" code from a single source? will this work or will compilers scream about this?
It is a mechanical inject the code here device. You can include a text file containing Goethe's Faust if you wish to. You can put it anywhere, even in the middle of a function (of course, #include needs a fresh line!).
However, it's strong convention to only use #include for header files. There may be reasons where I wouldn't object on it, for example pulling in machine-generated code or merging all translation units in a single file.
Not only does it work anywhere, but it can lead to some interesting techniques. Here's an example that generates an enumeration and a corresponding string table that are guaranteed to be in sync.
Animals.h:
ANIMAL(Anteater)
ANIMAL(Baboon)
...
ANIMAL(Zebra)
AnimalLibrary.h:
#define ANIMAL(name) name,
enum Animals {
#include "Animals.h"
AnimalCount
};
#undef ANIMAL
extern char * AnimalTable[AnimalCount];
AnimalLibrary.cpp:
#include "AnimalLibrary.h"
#define ANIMAL(name) #name,
char * AnimalTable[AnimalCount] = {
#include "Animals.h"
};
main.cpp:
#include "AnimalLibrary.h"
int main()
{
cout << AnimalTable[Baboon];
return 0;
}
Be sure not to put the usual include guards in any file that will be included multiple times!
Gotta agree with William Pursell though that this technique will have people scratching their heads.
Compilers will not complain, but everyone who has to maintain the code will.
It will work - more or less its semantic meaning is: place code in that file here
EDIT: For abusing usages of #include I can just recommend the following:
#include "/dev/console"
This allows for everything: a one-liner that can do everything, an error, its just a matter of compilation...
Should work, it's processed by your preprocessor, your compiler won't even see it.
#include and other preprocessor directives like #define or #import, can appear anywhere in the source, but will only apply to the code after that inclusion. It is meant to include the referenced code into the source file that calls it.
This MSDN page explains it quite well. http://msdn.microsoft.com/en-us/library/36k2cdd4(v=VS.71).aspx
include is handled by the preprocessor and is a mechanism to inject code. There are no restrictions on the file being included or where this #include is placed in your code (thought it should be in its own line). As long as the file specified can be found by the preprocessor it will import its contents into the current file.
Conventionally you do this for header files. I've seen this being done with cpp files during template instantiation (with proper #ifdef so you don't include it multiple times causing multiple symbol definition error).
If you have a long constant, you can do this for other file types as well. (Though there are better ways of handling long string constants)
I've been working with C++ for a good couple of weeks now, but the mechanism behind header files (or the linker I suppose?) confuses the heck out of me. I've gotten in the habit of creating a "main.h" to group my other header files and keep the main.cpp tidy, but sometimes those header files complain about not being able to find a different header file (even though it's declared in the "main.h"). I'm probably not explaining it very well so here's an abridged version of what I'm trying to do:
//main.cpp
#include "main.h"
int main() {
return 0;
}
-
//main.h
#include "player.h"
#include "health.h"
#include "custvector.h"
-
//player.h
#include "main.h"
class Player {
private:
Vector playerPos;
public:
Health playerHealth;
};
-
//custvector.h
struct Vector {
int X;
int Y;
int Z;
};
-
//health.h
class Health {
private:
int curHealth;
int maxHealth;
public:
int getHealth() const;
void setHealth(int inH);
void modHealth(int inHM);
};
I won't include health.cpp because it's a bit lengthy (but does work), it does have #include "health.h".
Anyways, the compiler (Code::Blocks) complains that "player.h" can't find the types 'Health' or 'Vector'. I thought that if I used #include "main.h" into "player.h" it would be able to find the definitions for Health and Vector sense they're included in "main.h". I figured they would they would sort of tunnel their way though (player.h -> main.h -> health.h). But that didn't work too well. Is there some kind of a diagram or video that could clarify how this should be set up? Google wasn't much help (nor my book).
The best way to think of your header files are as an "automated copy-and-paste".
A good way to think about it (although not how this is actually implemented) is that when you compile a C file or C++ file, the preprocessor runs first. Every time it encounters an #include statement, it will actually paste the content of that file instead of the #include statement. This is done until there are no more includes. The final buffer is passed to the compiler.
This introduces several complexities:
First, if A.H includes B.H and B.H includes A.h, you've got a problem. Because every time you want to paste A, you would need B and it would internally have A ! That's a recursion. For this reason, header files use #ifndef, to ensure that the same part is not read multiple times. This is likely happening in your code.
Second, your C compiler reads the file after all the header files have been "flattened", so you need to consider that when reasoning about what is declared before what.
The other answers here have effectively explained the way header files and the preprocessor work. The biggest problem you have is the circular dependencies, which from experience, I know can be a royal pain. Also, when that starts happening, the compiler starts to behave in very odd ways and throw error messages that aren't super helpful. The method I was taught by a C++ guru in college was to start each file (a header file for instance) with
//very beginning of the file
#ifndef HEADER_FILE_H //use a name that is unique though!!
#define HEADER_FILE_H
...
//code goes here
...
#endif
//very end of the file
This uses preprocessor directives to automatically prevent circular dependencies. Basically, I always use an all uppercase version of the file name. custom-vector.h becomes
#ifndef CUSTOM_VECTOR_H
#define CUSTOM_VECTOR_H
This allows you to include files willie-nillie without creating circular dependencies because if a file is included multiple times, its preprocessor variable is already defined, so the preprocessor skips the file. It also makes it easier later on to work with the code because you don't have to sift through your old header files to make sure you haven't already included something. I'll repeat again though, make sure the variable names you use in your #define statements are unique for you otherwise you could run into problems where something doesn't get included properly ;-).
Good luck!
You have a circular dependency. Player includes main.h, but main.h includes player.h. Resolve this by removing one dependency or the other.\
Player.h should include health.h and custvector.h, and at this point, I don't think main.h needs any includes. Eventually it may need player.h.
includes work very simple, they just command preprocessor to add the contents of the file to where include is set. basic idea is to include headers that you depend on. in player.h you should include custvector.h and Health.h. In main only player.h, because all needed includes will be carried with player. and you don't need to include main.h in player.h at all.
it is good also to make sure that header is included only once. in this question general solution is given How to prevent multiple definitions in C? in case of Visual Studio you can use #pragma once, if Borland c++ there is also a trick but i forgot it.
You want to organize your #includes (and libraries, for that matter) in a DAG (directed, acyclic graph). That's the complicated way of saying "avoid cycles between header files":
If B includes A, A should not include B.
So, using "one big master main.h" is not the right approach, because it's hard to #include only direct dependencies.
Each .cpp file should include its own .h file. That .h file should only include things that it itself requires to compile.
There is usually no main.h, because main.cpp nobody needs the definition of main.
Furthermore, you'll want include guards to protect you against multiple includes.
For example
//player.h
#ifndef PLAYER_H_
#define PLAYER_H_
#include "vector.h" // Because we use Vector
#include "health.h" // Because we use Health
class Player {
private:
Vector playerPos;
public:
Health playerHealth;
};
#endif
-
//vector.h
#ifndef VECTOR_H_
#define VECTOR_H_
struct Vector {
int X;
int Y;
int Z;
};
#endif
-
//health.h
#ifndef HEALTH_H_
#define HEALTH_H_
class Health {
private:
int curHealth;
int maxHealth;
public:
int getHealth() const;
void setHealth(int inH);
void modHealth(int inHM);
};
#endif
The only time you want to aggregate a bunch of #includes into a single header is when you're providing it as a convenience for a very large library.
In your current example, you're going a little overboard - each class doesn't need its own header file. It can all go in main.cpp.
The c preprocessor literally inserts the file from a #include into the file that includes it (unless it has already been inserted, which is why you need the include guards). It allows you to use the classes defined in those files because you now have access to their definition.