Order of functions and function prototypes?

I wanted to change a working sketch (a .ino file) into a .h file so I could put it in a CommonCode directory and refer to it from a skeleton .ino file - like this

Complete contents of ProjectA.ino

#define MOTORA

#include ".....CommonCode/Project.h"

When I did this I discovered that the compiler needs to have functions defined before they are referred to, even though that wasn't necessary when Project.h was used as Project.ino. I had to add function prototypes above the setup() function. When I did that it compiled without error. I haven't yet tested to see if the sketch actually works as I don't want the smoke to escape.

I'm curious to know why the compiler thinks things have changed and if there is any way to get it to work the same as it did with Project.ino?

I hope this makes sense.

...R

The Arduino does various mucking about with code in your .ino file before it compiles it. Among other things, it tries to generate function prototypes for all the functions you have defined and puts them somewhere near the top of the sketch, in a location which is usually correct but sometimes not.

When you put your code in a 'C'/C++ source or header file it doesn't have this mucking about done and needs to conform to the usual 'C'/C++ requirements to be compilable. Among other things that means that all types and functions have to be declared or defined before they are used.

Putting executable code in header files is unconventional and not recommended. What you should do is put the code in a C++ source file, and put the corresponding external declarations in the associated C++ header file, and #include the header file in any other files that need visibility of those declarations.

Bear in mind that due to the mucking-about, the source code invoked by the compiler is not in the same directory as your original sketch and will usually be in a temporary directory, so any relative file references are likely to be problematic. If you implement the shared code as an Arduino library this works out much cleaner.

Thanks Peter.

The compiler doesn't seem to care whether the included sketch is called .ino, .cpp or .h

I'm lazy. If it works (and it seems to) it will do. I never liked the fragmentation of C projects into so many files that make it almost impossible to figure out easily what anything is.

Another small question - to save starting another Thread ...

How should I include a file that is not in the current directory?

I thought #include "../CommonCode/ffff.h" would work but so far the only way I have got it to work is using the fully qualified path name. (I'm using Linux).

...R

The compiler doesn't seem to care whether the included sketch is called .ino, .cpp or .h

The compiler does care a lot, the IDE translates the .ino to a .cpp/c file . The compiler (gcc will only deal with .cpp, .c, .h files.

Mark

Robin2:
The compiler doesn't seem to care whether the included sketch is called .ino, .cpp or .h

The compiler cares a great deal, which is why you're having the problems you're having.

Robin2:
I'm lazy. If it works (and it seems to) it will do. I never liked the fragmentation of C projects into so many files that make it almost impossible to figure out easily what anything is.

What I described is a standard conventional 'C'/C++ structure, which is how the language was designed to be used and works on projects of all sizes. The approach you described is a nasty hack which can be made to work but is not a good approach.

Robin2:
How should I include a file that is not in the current directory?

If you're building it using the Arduino IDE, put it in a library. Your other option is to not use the Arduino IDE.

holmes4:

The compiler doesn't seem to care whether the included sketch is called .ino, .cpp or .h

The compiler does care a lot, the IDE translates the .ino to a .cpp/c file . The compiler (gcc will only deal with .cpp, .c, .h files.

Mark

Sorry, but I'm not sure what you have added here? Your answer seems to be the same as the question.

...R

Sorry, but I'm not sure what you have added here?

I think it is what has been taken away (.ino) that is important, rather than what has been added (.c).

I wonder if I have run foul of C++ purists :slight_smile: - which seems odd in view of how the Arduino system "abuses" the rules.

I said earlier that the compiler (meaning the Arduino IDE "verify" button) doesn't care what file type is given to files that are identified with #include. Just now I renamed the file to Planet.blahblah and that was accepted and compiled.

The only problem I have now (it's really just an inconvenience) is that I can't figure out how to include a file in a different directory without using the fully qualified path name.

I had assumed that #include "../CommonCode/Planet.h" would work, but it doesn't.

Is it possible to include files without giving the full pathname, and if so, how.

Thanks.

...R

I said earlier that the compiler (meaning the Arduino IDE "verify" button) doesn't care what file type is given to files that are identified with #include. Just now I renamed the file to Planet.blahblah and that was accepted and compiled.

The compiler never sees the #include statements. The preprocessor does, and copies the contents of the named file into the file containing the #include statement. The compiler ignores the #include statements.

The name of the file, or it's extension, to be included has nothing to do with the behavior of the preprocessor (or compiler).,

I had assumed that #include "../CommonCode/Planet.h" would work, but it doesn't.

Enable verbose compiling to understand why. The .ino file is copied to another directory. Any #include files, referenced in an .ino file, that are located in a libraries folder (or subfolder of a libraries folder) are also copied. Any source files matching the name of a header file in a library directory, are also copied to the build directory.

When the preprocessor runs, relative paths, like ../CommonCode are not relative to the build directory, so the include fails.

Robin2:
I wonder if I have run foul of C++ purists :slight_smile: - which seems odd in view of how the Arduino system "abuses" the rules.

I don't consider myself a 'C' purist - I am just trying to explain that the problem is caused by the way the Arduino IDE mucks about with your code before it compiles it. I'm also advising you that the file layout you're trying to use is not how Arduino was designed to be used and is also not how 'C'/C++ was designed to be used, and is not good practice.

PaulS:
When the preprocessor runs, relative paths, like ../CommonCode are not relative to the build directory, so the include fails.

Thanks Paul, that's clear. I think I can live with using a fully qualified path name.

...R

PeterH:
..... not how Arduino was designed to be used ....

I only have this problem because the Arduino system insists on having the .ino file in a directory with the same name - thus only one project per directory.

Anyway, as far as I can see I now have a very simple workaround that meets my requirement to minimize the risk of uploading the wrong code to a device and letting the smoke out.

...R

Robin2:
I only have this problem because the Arduino system insists on having the .ino file in a directory with the same name - thus only one project per directory.

I'm less charitable - I think you have the problem because of several mistakes in the design of the Arduino IDE. It seems to me that the designers have tried to make Arduino code behave a bit like Java, which was IMO a daft thing to try to do since C++ and Java are plainly very different, and has not been done well, and has introduced various non-obvious side effects which mean the Arduino code doesn't behave like conventional 'C'/C++ code. So any 'C'/C++ knowledge you bring to Arduino is liable to lead you astray here, and Arduino coding habits are going to lead you to trouble if you apply them in a non-Arduino C++ environment.

To reiterate: if you want to share code between sketches, the Arduino way to do that is to put it in a library containing header and source files.