Tutorial for creating multi cpp file arduino project

Ok, let’s give this a try…
After some googling I found this. It is based on the implementation of an arduino-capable VS-extension. First cite, no offense :stuck_out_tongue::

In a nutshell:

  • If you don’t want to learn about C++ declarations and header files, stay with .INO files
  • If you have a more complex sketch with many separate source files that use classes and methods from each other, you will have more control and overview if you use “classic” C++ .CPP and .H files

Nevertheless based on the implementation choosen in this extension you could mimic the standard Arduino-IDE behaviour by edediting files like this:

  1. rename your “main”-file with the setup and loop functions to *.cpp and add #include "Arduino.h" at the very top of this file
  2. rename all other *.ino-files that are part of your project to *.h
  3. At the end of your “main”-*.cpp-file write #include "foo.h", #include "bar.h", etc. for every *.h-file you have where foo and bar are the actual names of the needed files
  4. create function prototypes in a seperate file. To do this create a new file called prototypes.h and add a prototype for each function defined in one of your other *.h-files there.
  5. include the created prototypes.h (#include "prototypes.h") at the top of your “main”-*.cpp-file right below #include "Arduino.h"

Now you are ready to go…
Example:

main.ino:

void setup() {
    ;
}

void loop() {
    ;
}

library.ino:

int add(int a, int b) {
    return (a+b);
}

Those get turned into
main.cpp:

#include "Arduino.h"
#include "prototypes.h"

void setup() {
    ;
}

void loop() {
    ;
}

#include "library.h"

library.h:

int add(int a, int b) {
    return (a+b);
}

prototypes.h:

int add(int a, int b); // This is a function prototype - basically the function-head without a {}-block ended by a semicolon, you need one of those for each function you want to use

I really want to point out that this style isn’t particulary beautiful… no, it really is bad, very bad as it could cause a lot of errors… but it seems this is the “easy” way to convert a *.ino-project quickly.

  • Why does this work?
    #include is a so called preprocessor directive. Before you code gets translated to something your Arduino can work with (by a compiler and a linker), the preprocessor does some simple stuff (like text replacement). By telling the preprocessor to include something (everything in your source-code beginning with an # is a preprocessor directive) you basically tell him to simply copy/insert the text from the included file at that point. The file created is simply a text-file with all the included files copied together into one…
  • Why do you need those strange function prototypes?
    The compiler translating your sourcecode works top-to-bottom. When you include the *.h at the end of your “main”-file the moment you might call the function add() in your loop the compiler doesn’t know there is a add()-function defined; you get an error. To prevent that you have a prototype at the top so the compiler knows that somewhere there is a definition of that function and he doesn’t care about it anymore, no matter where the actuall definition is.
void add(int a, int b); // A function prototype or declaration to "please the compiler"

void add(int a, int) { // The actual function definition with the logic
    return (a+b);
}
  • Why not just #include all those *.h-files at the top of my “main” so I don’t need prototypes?
    Well, idk, this is a bad style in eather way, I just stuck with the explenation given here. Just make sure you include other files AFTER the Arduino.h so all following files inserted “have access” to it.

In the end I still recommend:
Just do it the proper way and learn splitting into multi-file projects the “normal” C/C++ style; it’s not even that big of a step from what I just wrote… You can not just place functions in other files but global variables and classes too, not to mention that it provides a way clearer structure for large projects, maybe even projects with multiple people.

10 Likes