variable "was not declared in this scope" for functions in separate .h/.cpp file

Hi guys. Very experienced in VisStudio C++ for PC but rusty and just starting with Arduino. I'm finding the structure is a little different.

I have a long winded project for an Arduino Mega which I have working in a very one dimensional .ino file only form. In essence it's nothing functionally very complicated, just a number of switches and LEDs compiling circuitous selection logic into a coded packet and pushing it out over a serial line. That all works fine but is long and unwieldy being in a single file.

So I'm now rewriting it and splitting it out into a number of classes and additional files. The new classes don't give too much trouble as they are stand alone encapsulated functionality. One thing I read about and have tried to set up is the idea of the .ino only containing the core Arduino functions and all other basic non class member functions being moved into a pair of "HelperFunction" files. This seemed a tidy approach so I went with it.

So now I have a HelperFunction.h for declarations and a HelperFunction.cpp for definitions. These functions are called from within the setup() and loop() functions in the .ino, so HelperFunction.h is #include-d into the .ino file. It seems to me at first sight that the Arduino approach is to basically declare a lot of globals at the start of the .ino file. As you need to access these from within the HelperFunction .h and .cpp files I would have hope dthey were global in scope and be seen but this is not what I'm finding. It compiles a lot of "was not declared in this scope" errors. Moving them to the HelperFunction header file causes other problems and to be honest just plain feels wrong. I don't know what the Arduino approach to this issue is.

I obviously don't really have a clear picture of the relationship between the .ino file and other non-class oriented files like my HelperFunction pair. Can someone point out where I'm going wrong in making this work? Or have I got the concept of those HelperFunctions wrong in some way?

Can someone point out where I'm going wrong in making this work?

Well, the most obvious thing is that you didn't post your code.

:confused: I kind of did think of that Paul and, as I did try to get across, the code is very very long and spanned a number of separate files and for the most part irrelevant. I had hoped that, as the query was a sort of general structural issue, it would not be necessary to burden you all with a lot of unnecessary code to just advise on a question which was basically about how to structure files in Arduino code.

I obviously don't really have a clear picture of the relationship between the .ino file and other non-class oriented files like my HelperFunction pair. Can someone point out where I'm going wrong in making this work? Or have I got the concept of those HelperFunctions wrong in some way?

Don't worry, I'll figure it out somehow, the answer will be out there if I keep looking I'm sure.

the code is very very long and spanned a number of separate files and for the most part irrelevant.

So write a small program that illustrates the problem and show us that.

It sounds like you need an extern declaration for the variables that are defined in the .cpp file. But without seeing some code it's impossible to say if that is in fact the case. Google "C++ extern" and see if you don't learn what you're looking for.

Dooohhhh for me! Of course UKHeliBob, plain never thought of that. So here is the problem in a few lines.

(file "Test_Sketch.ino")

#include "Helper.h"        // Made no difference if left out

int iVar;                      // Made no difference initialising it here with int iVar=10; either

void setup() {
  iVar = 10;
}

void loop() {
  testFunction();
}

******************************

(file "Helper.h")
void testFunction();

******************************

(file "Helper.cpp")

#include "Helper.h"

// Helper function to utilise iVar declared in .ino file
//
void testFunction()
{
    int iJunk = iVar + 10;
}
The Error Message:


C:\DOCUME~1\Albert\LOCALS~1\Temp\arduino_build_471212\sketch\Helper.cpp: In function 'void testFunction()':

Helper.cpp:7: error: 'iVar' was not declared in this scope

     int iJunk = iVar + 10;

                 ^

C:\DOCUME~1\Albert\LOCALS~1\Temp\arduino_build_471212\sketch\Helper.cpp:7:9: warning: unused variable 'iJunk' [-Wunused-variable]

     int iJunk = iVar + 10;

         ^

exit status 1
'iVar' was not declared in this scope

The idea of #including Helper.h in Test_Sketch.ino felt unnecessary in principle to me and it made no difference if I left it out as testFunction() was still found, but it may well be necessary. Helper.h and Helper.cpp seem to be unencapsulated so would seem to be open but this should mean that they have access to iVar.

If I shifted the declaration of iVar into the Helper.h file, despite the #include of Helper.h in TestSketch.ino that then generates a multiple declaration error with respect to iVar.

Either this is down to my being very rusty or I am assuming that the Arduino environment is more simple than it would first seem. Does this make the issue clearer?

Delta_G: It sounds like you need an extern declaration for the variables that are defined in the .cpp file. But without seeing some code it's impossible to say if that is in fact the case. Google "C++ extern" and see if you don't learn what you're looking for.

Where is iVar defined?

hint extern to Helper.cpp

To me that's odd Bulldog. Not in a C++ sense but from what I had read about the Arduino .ino setup. I've cleared the error by declaring and defining the variable in Test_Sketch.ino and redeclaring it in Helper.h as extern. And everything is hunky dory.

I had been led to believe that the Helper files were almost a simple textual extension of the .ino file and I stupidly assumed that they would be the same scope. Once that assumption was in there I couldn't get past it. This is obviously not the case and it has to be seen as a totally separate entity.

With the number of variables in my original sketch, lots of arrays in there, I wonder if the separating out into a Helper file pair is sensible. I'll start with stripping out classes and see what gets left I think.

Thanks for the tactful massaging from everyone who replied, it really is just down to lack of experience of the environment and a few mental blocks.

bordonbert: To me that's odd Bulldog. Not in a C++ sense but from what I had read about the Arduino .ino setup. I've cleared the error by declaring and defining the variable in Test_Sketch.ino and redeclaring it in Helper.h as extern. And everything is hunky dory.

I had been led to believe that the Helper files were almost a simple textual extension of the .ino file and I stupidly assumed that they would be the same scope. Once that assumption was in there I couldn't get past it. This is obviously not the case and it has to be seen as a totally separate entity.

Remember that C++ has so-called "file-scope." Getting a global to play within each of the files that use it requires you to reference that (i.e. extern). Think of it like a forward declaration of a function.

As a side note, you could likewise encapsulate a variable in a file by using the static keyword.

and redeclaring it in Helper.h as extern.

You did not redeclare the variable. You said "there is a variable with this name and type defined in some other compilation unit. That is what I'm referring to when I use this name".

Your impression that the IDE will just mash them all together is correct ONLY if all the files are .ino files. For .h and .cpp files the normal C++ rules apply.

Thanks Delta-G, that is absolutely the crux of the problem! (Apart from my failing memory that is.)

Bulldog, yes C++ has file scope and I do use extern/static but, as you can see, I had totally got the wrong end of the stick about the Arduino approach when I read up on that to get started. Once I was on the wrong thinking track my brain couldn't unthink it.

I also take your point Paul, using that wording was very poor. And I'm normally I'm plain old Mr pedantic with how I word things!

As a last thing, with Delta-G's advice I've just put the Helper.cpp code in a new text file minus the #include, and renamed it Helper.ino. I then removed Helper.h and Helper.cpp and the #include in the Test_Sketch.ino and the whole things builds. That bears out what Delta-G said about .ino files being mashed together. Is this an acceptable approach to splitting out a large base .ino file? I would keep classes defined in classic separate .h/.cpp fashion but it seems basic functionality in the core sketch could be arranged like this for convenience and ease of editing.

Is this an acceptable approach to splitting out a large base .ino file?

Yes, but... If you KNOW how the IDE mashes the ino files together, it is. If you don't, you are playing with fire. I've been burnt too often, so I don't do that.

Yes, you CAN name the ino files appropriately, to make the IDE mash them together in the proper order. But, I prefer to name the files to reflect what they contain, not the order that I want them mashed together.

"I prefer to name the files to reflect what they contain, not the order that I want them mashed together."

I go with the order I expect, using the tabs feature of the IDE, for example: sketch_name, then a_presetup, b_setup, c_loop_start, d_loop_end, e_functions, f_other_functions, and they all end up as .ino in the sketch_name folder.