.cpp and how to use em

so im working on a project, using issue one of the arduboy magazine as a reference, specifically the article by @JO3RI about using multiple files,

ive had ALOT of problems, though with @Pharap pointing me in the right direction ALOT (as usual) im geting closer

the problem im having right now is the only mention of .cpp files in that article is that team arg dosent use them, with the exception of “virus”, so i downloaded the source to see if i could wrap my head around it , i can not

from what i understand, .h is for defines and .cpp is for using what you defined in the .h

so,
question 1
in the .h you are suposed to only include whatever is needed, define what needs defined and declare any variable needed for the accompanying .cpp file. and in the .cpp file itsself you put in the actual code?

question 2, maby im wrong here but does prety much everything (besides the includes defines and initializing of variables) in .h or .cpp NEED to be inside a function

3, can you put multiple functions in one function like so
void enemy() {
drawenemy();
enemiespawn();
enemyhurt();
enemymove();
};

1 Like

So I’m a bad source, but maybe my learning experience can get you started. All these files are basically trying to convince the compiler that they are indeed legit and do work. Each tab, or file, you have open in arduino is ‘instanced’, so, for example, if you declare a variable in one it isn’t reflected in the others. That’s where the cpp and h files come in. I’m probably going to screw up terminology, so I apologize (C++ is not my first language).

The .h file, or header, is basically a way of exposing functions and values to a particular tab and must be specifically included use #include.

#include "foo.h"

Whatever you declare here will now be visible to whatever file has included it. The .cpp file then contains the definitions, which is basically what these functions will do. What it comes down to is that when the compiler goes to put all this stuff together, it is able to see all these different pieces and properly compile. For example, let’s say you wanted to shift a bunch of functions to another file, if you simply put them in the other file you’ll get a scope exception when you try to compile. So you need to use the header to declare it:

// foo.h
void myFunction();

Then use the .cpp file to define it:

// foo.cpp
#include "foo.h";

void myFunction() {
  return;
}

And lastly, you can now call it from your .io file:

#include "foo.h"

void setup() {
  myFunction();
}
void loop() {

}

For a more practical example, and I’m sure I’ve done this wrong, you can define arduboy this way so that you can call this library from these other functions as well:

// foo.h
#ifndef FOO_H
#define FOO_H
#include <Arduboy2.h>

extern Arduboy2 arduboy;

#endif
// foo.cpp
#include "foo.h"

Arduboy2 arduboy;
#include "foo.h"

void setup() {
	arduboy.boot();
}

void loop() {
	
}

Any file that includes “foo.h” will now be able to call on arduboy to perform the library functions. Putting all this together means that you can push more than just const variables to another file, and can actually declare functions or other parts of your program to help keep things tidy. As far as I understand, and my guess to why people don’t do this often, is because it’s a huge pain in the butt.

EDIT: I forgot to mention, the reason people may choose to use a h file is complicated, but it’s basically a way of declaring things before they are defined, so for example, if you write a function that uses another function, or if you have variable arguments, this ensures that the compiler will know it exists and work properly. Again, as far as I can tell almost all of this stuff is just to get the compiler to be able to understand what you’ve written, and using .h and .cpp is just a way to make things a bit easier on yourself (at the cost of making things harder). You can simply define everything in the .h file and ignore the .cpp, which is what team ARG is saying they do. They simply write their functions and definitions to the header and call it a day.

2 Likes

This is a bit of a tough question.
Before I give my full, longwinded answer, I’ll give a few brief answers to your questions:

Sort of.
You are supposed to only include the bare minimum that your header file needs.
Global variables are a bit of an issue for header files, @Hyomoto’s answer covers how to extern them to make them easier to work with.
(Personally I avoid global variables everywhere but the main .ino file so it’s not really an issue I have much experience with.)

Again, sort of.
Code that runs/executes that isn’t used to initialise a global variable (or a field in a class) needs to be in a function.
Code that returns a value/creates a value doesn’t have to be in a function if it initialises a global variable or (in some cases) a field in a class.
For example:

int someGlobalVariable = 36 * 5 + 1;
int anotherGlobalVariable = someFunctionReturningInt(3, 4, 5);

But you couldn’t just write (for example) arduboy.begin(); outside of a function. There’s actually some rules behind why this is and why int thing = returnsInt(); is different from just having returnsInt();, but they’re complicated.

In a word: yes.
In full: yes, as long as those other functions have already been declared.

You can call a function as many times as you like (and as I explain in a moment, you can declare it as many times as you like, but you can’t define it as many times as you like).


I think that really to understand .h and .cpp files you first need to know the difference between a ‘declaration’ and a ‘definition’ (in C++ terminology) and a bit about how the compiler works.

This is going to be a bit long, but like I say, it’s a tough question, and normally a tutorial would explain it a bit at a time.


Declaration vs definition:

@Hyomoto’s answer sort of touched on this already via demonstration but I want to focus on explaining the concept because it can be helpful to know about the difference between declaration and definition.

A declaration is a bit of code that says “this thing exists” but doesn’t specify all the details of that ‘thing’.

A definition is a bit of code that not only says “this thing exists” but also says “this thing is this and/or does this”.

You can have as many declarations as you like, but each ‘thing’ can only have one definition and the compiler will complain if you try to give the same ‘thing’ more than one definition (which is one of the main reasons why you need include guards or #pragma once).

(Note, if you declare something multiple times, it has to be declared in the same way (you can’t suddenly change the return type or forget to mention an argument) and likewise you can’t declare two different things with the same name.)

Function:

For example, for a function a declaration would look like this:

void doSomething(int arg0, int arg1);

Which just introduces the function by declaring its name, its arguments and its return type.

Whereas a definition would look like this:

void doSomething(int arg0, int arg1)
{
  // code goes here
}

Which not only introduces the function, but actually says what it does as well.


Compilation Process:

When the compiler does the compiling, it starts with the header files (.h files) and processes them all (e.g. handles all the #defines, the #includes and the #pragmas, then does some other magic with the functions and stuff), then it processes all the .cpp files (e.g. handles includes, other stuff).

The actual process is long and complicated, but basically all you need to know is that .h files are processed before .cpp files and they only have to declare things, they don’t necessarily have to define things.


The intention of having separate .h and .cpp files is that .h files are supposed to contain the declarations of all the things, and the .cpp files contain the definitions.

Part of the reason behind that is that one of the ways to make code compile for different processors is to use the same .h files but change the .cpp files. i.e. the general structure stays the same but you change the functionality slightly.

Another reason is because then someone who wants to know how to use your code but not necissarily how it works can just read the .h file and see what that .h file declares without having to read all the code in the .cpp file that does the actual implementation.

Lastly the whole reason .h and .cpp files exist is an accident of history. C++ was originally built as an extension of C (though it isn’t any more because the rules changed and the two languages diverged) and back when C was designed there hadn’t been as much research into compiler design as there is now. Modern languages don’t need header files because of the way modern compilers are built and the way modern languages are defined, but back then the header system seemed like a good idea for various reasons.


If you want to know more there’s a medium-weight explanation here, and a slightly more in depth one here.
There’s probably some even more in depth answers elsewhere, but you don’t necessarily need to know everything about the compiler process to know how to use .h and .cpp files.

(If you don’t already, I recommend reading StackOverflow questions and answers from time to time, there’s some very good stuff there.)

(If you intend to ask a question there though, make sure to read the rules first and check you’re not asking something that’s already been answered, some of the users get a bit annoyed at duplicate questions and the site isn’t very beginner friendly. I’m pretty sure their unofficial motto is “this is not a forum”.)

2 Likes

Actually, the compiler doesn’t automatically processes .h files. In order to have a .h file processed, you have to #include it in a .ino or .cpp file. A .h file will be processed at the time the #include of it is encountered. (Exception: In the Arduino environment, Arduino.h is automatically included at the start of the sketch when it’s compiled.)

If used as intended, the Arduino environment tries to “modernise” C++ in this way. (At least, it tries to make things easier to get a program up and running without worrying about headers and declarations).
TL;DR: Multi-file sketches can consist of only .ino files and don’t need function declarations.

The concept is:

If you’d like to write your sketch as multiple files, for organisational purposes, you can make them all .ino files. The .ino file that matches the name of the sketch (i.e. matches the name of the folder that the sketch is in) is the “master” .ino file. By convention, the master file will usually contain the setup() and loop() functions (at least). You can then add as many more .ino files as desired, named whatever you like, with functions and data grouped for easy maintenance and readability.

“Under the covers”, when a sketch is compiled the Arduino build process will combine all the individual .ino files into a single .cpp file. It will then analyse the file and create definitions (also called prototypes) for all the functions. The automatic creation of function prototypes eliminates the need to create any .h files, in most cases.

It should also be noted that the Arduino IDE hides the .ino extension when displaying the file names in the tabs (by default) and you don’t have to include the extension when naming a new tab.

Thus, by using only .ino files and no .cpp or .h files you can just define variables and write functions, and not have to worry about needing function declarations or #includes.

Now comes the argument: But this makes it confusing when a beginner who learned in the Arduino environment tries to write a “real” C++ program in the future. It also makes it difficult to port an Arduino sketch to a true C++ environment.

Learning C++ is not the intent of Arduino. It’s to allow artists and makers to add blinking lights, and a propeller that spins when you push a button, to their project with less amount of programming effort required. For the Arduboy, along with using the Arduboy2 and other libraries, it makes it easier for a beginner to create a game.

This is why I like to view the Arduino environment as using a new language that is very very similar to C++ but somewhat simplified.

For more details, refer to the Arduino Build Process.

@Pharap, Are you implying the Arduino “lie-to-children” is a good thing or a bad thing?

I’m saying my answer is a bit of a lie-to-children.

I’m providing a middle ground answer that is intended to be easy to understand but does not necessarily include all the details.

Althought while I think of it, I never said the compiler ‘automatically’ processes .h files, I just said it ‘starts’ with them (obviously it does other stuff first, but for the sake of simplicity).

I’ll admit I didn’t explicitly state that header files need to be included, but I thought @curly already knew that.

1 Like

I think a better term for the Arduino environment is “framework”. A framework is like a library, except the framework calls your code instead of your code calling the library.

I don’t see a lot of frameworks used for C/C++, and at least one list of C/C++ “frameworks” is mostly libraries. But they’re popular with higher-level languages for things like web apps, async systems, etc.

Even the magic of adding a header file to .ino files isn’t unique, as some frameworks will add file types that get preprocessed to produce code files.

life is so much easier when you put everything in one file… but… when life is easier do you realy learn anything?

this project is a pain in the butt (but the good out weighs the bad)

If you use only .ino files you can write your code exactly the same as if they were one single big .ino file.

that is good to know, i thought thats what you were saying but i wasnt 100% shure, so do you still need to include all of the additional ino in the main file? (id assume so?)

When your program is small maybe, but the larger it gets the more difficult it gets to find things.

Switching tabs is generally easier than scrolling around looking for something specific.

“Nothing worth having comes easy” as they say.

1 Like

No, you don’t need #includes in the main .ino file for all the other .ino files.

You only need #includes in the main .ino file for any libraries that you want to use, such as:
#include <Arduboy2.h>
#include <ArduboyTones.h>

And you don’t need to put these #includes for the library headers in any of the other .ino files, only the main one.

You can think of it as the same as making one big .ino file and then just splitting it into multiple smaller .ino files afterwards, without making any other changes or additions.

So, using only .ino files is pretty easy.

Maybe I’m naive but it’s not that much harder to use .h and .cpp. I can’t argue that implementation is going to dictate whether or not it is useful, but it seems like learning to use this concept improves flexibility and manageability. It’s a tad bit more work to set up, but after that it IS as easy as just using .ino files. If you only use .ino files you’ll need to do a lot of prototyping. Not a major issue, but at that point you might as well include a header. And if your project is complex enough use an .h file. While you are there, a .cpp file is really just one line of additional complexity.

1 Like

@MLXXXp thank you for being very specific

@Hyomoto you are probably right and eventually I would like to do just that, but right now I’m confused enough so simpler is better.

1 Like

Huh? If you use .ino files you shouldn’t have to do any prototyping in most circumstances. From the Pre-Processing section of the Arduino Build Process document:

Prototypes are generated for all function definitions in .ino files that don’t already have prototypes. In some rare cases prototype generation may fail for some functions. To work around this, you can provide your own prototypes for these functions.

Whoops, you are right. I’m being dumb.