[Solved] Having issues breaking a project into .h and .cpp files

Heya,

I have a project that up to this point has existed in several .ino files. This has worked for now, but I was interested in trying to move away from the alphabetical .ino compilation order, while at the same time learning more C++.

I tried to move the .ino files almost literally into .h and .cpp files, however the project .ino file encounters an issue when compiling. I created a small test project and searched a lot for answers, but so far have come up blank.

The Error

C:\Users\<path to my app data>\cc670oLO.ltrans0.ltrans.o: In function `loop':
E:\<path>\Projects\Arduino\potato-test\potato-test/potato-test.ino:8: undefined reference to `runPotato()'

potato-test.ino

#include "test/potato.h"

void setup() {
    potatoes = 2;
}

void loop() {
    runPotato();
}

test/potato.h

const unsigned char POTATO_LIMIT = 5;

extern unsigned char potatoes;

void runPotato();

test/potato.cpp

#include "potato.h"

unsigned char potatoes = 0;

void runPotato() {
    if (potatoes < POTATO_LIMIT) {
        potatoes++;
    }
};

I am new to the whole declaration / definition distinction, so I fully expect to have made some sort of fundamental mistake here that I can't see.

I have looked into having a blank .ino file and running the project from a .cpp file, but that did not work (same error).

I am aware of C++ name mangling, however I cannot see how that would apply here.

Any help or pointers are appreciated.

See my Reply #3 in this Thread,

Your filenames do not seem to match up. You are including "test.h" but you save the file is "potato.h"

You need to have a directory called "potato_test"

Inside that folder is potato_test.ino, potato.h, potato.cpp

potato_test.ino

#include "potato.h"

void setup() {
    potatoes = 2;
}

void loop() {
    runPotato();
}

potato.h

const unsigned char POTATO_LIMIT = 5;

extern unsigned char potatoes;

void runPotato();

potato.cpp

#include "potato.h"

//const unsigned char POTATO_LIMIT = 5;

unsigned char potatoes = 0;

void runPotato() {
    if (potatoes < POTATO_LIMIT) {
        potatoes++;
    }
};

Constants go into the .h file so they can be used everwhere.
Variables are defined in the .cpp file and declared 'extern' in the .h file

@gfvalvo

I did see your post while searching, and as far as I can see I have done everything that you mentioned. Is there something more specific about what I am doing that seems wrong to you?

@blh64

Apologies, those were errors in the original post; I have amended the code samples and paths.

Could it be that the compiler isn't seeing potato.cpp? Do the .h and .cpp have to be in the Arduino project root folder? I currently have them in the /test subfolder.

Edit:

I moved the .h and .cpp files into the root directory and they now compile correctly. @blh64 was right on the money.

To summarise:

  • All project files need to be in the root
  • Consts can be declared and defined in the .h
  • Variables must be declared extern in the .h and defined in the .cpp
  • You need to #include the .h in the .cpp

FYI... you can put your .h files and .cpp files in a subfolder, but is has to be names 'src' and then the tool chain will still work. Other subfolder names will not

Of course, you have to adjust your include to be "src/potato.h"