correct way to include .cpp and .h files in an Arduino sketch

Madivad picture Madivad · Jan 28, 2014 · Viewed 71.9k times · Source

First, the problem:

main sketch file:

char foo;            // required to clean up some other problems
#include <Arduino.h> // tried it in desperation, no help
#include "a.h"

void setup(){
  Serial.begin(9600);
  Serial.println("\nTest begins");
  for (int num = -1; num < 1; num++){
    Serial.print(num);
    if (isNegative(num)){
      Serial.println(" is negative");
    } else {
      Serial.println(" is NOT negative");
    }
  }
}

void loop(){}

// a.h

#ifndef H_A
#define H_A

boolean isNegative(int x);                  // Err#1
int anotherOdity();

#endif // H_A

// a.cpp

#include "a.h"

int isNegative(int x){
  Serial.println("I can't print this from inside my INCLUDE FILE"); //Err#2
  if (x<0) return true;
  return false;
}

int anotherOdity(){
  char ch[5];
  memcpy(ch,"1",1);  //doesn't work, memcpy not declared      // Err#3
}

The above, as is, doesn't compile and these are the errors I get:

In file included from a.cpp:1:
a.h:4: error: 'boolean' does not name a type
a.cpp: In function 'int isNegative(int)':
a.cpp:4: error: 'Serial' was not declared in this scope
a.cpp: In function 'int anotherOdity()':
a.cpp:11: error: 'memcpy' was not declared in this scope

The first problem is the boolean type, seems to suffer from some name mangling that the Arduino environment does, but that is generally fixed by the char foo; in the main file. And in certain situations, it is. But to use that type in the .cpp file generates this error.

I can see that Errors 2 and 3 are related, but how do I get these in scope? I realise that part of the problem is probably the #include itself (maybe) because Serial and memcpy aren't yet defined/declared? I tried including the the Arduino.h library, but that didn't help. Actually, it did help the boolean problem but only in the case of putting everything in the .h file (as I discuss further below), it doesn't help the above example.

If I put the three files together and have everything in the main sketch (.ino) file, it works as it should. But the idea here is that I want to break out some code and make my sketch more readable.

The closest I got to a solution was found here: http://liudr.wordpress.com/2011/02/16/using-tabs-in-arduino-ide/ where, after running my own tests, I determined that if I put EVERYTHING in a .h file, it works!

For example, leaving the main sketch file unchanged, if I delete a.cpp and create just a.h (as follows) it works!

#ifndef H_A
#define H_A

boolean isNegative(int x){
  Serial.println("I can't print this from inside my INCLUDE FILE");
  if (x<0) return true;
  return false;
}

int anotherOdity(){
  char ch[5];
  memcpy(ch,"1",1);  //doesn't work, memcpy not declared
}

#endif // H_A

This fixes the boolean problem (well.... I still need Arduino.h or char foo;), and it fixes the scope issues.

But it just feels wrong.

This isn't about creating a library of standard functions I could use across various sketches, it's all about breaking my code into smaller (readable) chunks, and keeping them all together in the project folder. I want to do this in the most correct way possible, it just seems to be I'm limited by the IDE. I'm sure I have a suitable understanding of how to put a header and associated .cpp file together (I hope that I have't got that part wrong).

I am totally self taught with everything C/C++ and have only really got into programming micros very recently.

I have researched this through the depths of google and am just continually coming up short.

Without resorting to hacks and keeping it simple for folk like me, how can I best put together the above examples so that the Arduino IDE/gcc will compile it?

edit: I thought I would include just SOME of the tabs I have open here to show that I really have done some research on this!

http://arduino.cc/en/Reference/Include

http://arduino.cc/en/Hacking/LibraryTutorial

http://forum.arduino.cc/index.php/topic,124904.msg938861.html#msg938861

http://forum.arduino.cc/index.php?topic=84412.0 (this is where I found the char foo; solution)

http://liudr.wordpress.com/2011/02/16/using-tabs-in-arduino-ide/

Including .cpp files

Keeping all libraries in the Arduino sketch directory

C++ Header and CPP includes

Answer

user2711915 picture user2711915 · Jan 28, 2014

The reason it doesn't work is that you need to include something in your a.h or a.cpp files.

Try this in your a.h file and then everything should work.

#ifndef H_A
#define H_A

#include <Arduino.h> //needed for Serial.println
#include <string.h> //needed for memcpy

...

The reason for this is that you can think of the compiler separately compiling each cpp file. A #include is in fact just an automated copy paste. When the compiler is coming to compile a.cpp, it doesn't know that Serial.println() exists, because it wasn't defined in a.h, which is the only other text that appears in a.cpp. The reason it works when you put it all in the header is that in your main cpp file you have included Arduino.h before the a.h include, so once those #includes have been copy pasted in its as if you just wrote the code there in the first place.

You can just write all your code in headers, but it isn't advisable for various reasons including efficiency at compile time (but as an arduino program can only be 32k, I don't think compile times are going to get too long!)