5

I am having troubles creating a collection of functions to be used in Arduino sketches and libraries. What I want is not a class, but simply a group of functions which do not require an object to be called; general utilities that can be helpful in any Arduino sketch, like an average of analog reads, or a little statistical tool.

Suppose I write a file called Utilities.h (I am not sure .h is the right extension to use in this case):

Utilities.h

#ifndef Utilities_h
#define Utilities_h
#include <Arduino.h>

void utility1(...){
...
}

float utility2(...){
...
}

//and so on

#endif

I then save this file in ../Arduino/libraries/Utilities. Whenever I want to use my utilities from this file directly in a sketch I type #includethe full path to the file (#include <Utilities.h> won't work).

The real problem is if I want to use this collection of functions in a library, like in the following example.

myClass.h

#ifndef myClass_h
#define myClass_h
#include "full path to Utilities.h"

class myClass{
 private:
  int a;
 public:
  myClass();
};

#endif

myClass.cpp

#include "myClass.h"

myClass::myClass(){
 a = utility2(...);
}

Whenever I try to #include <myClass.h> in my sketches and compile, I get 'multiple definition' error messages for the functions on my Utilities.h.

So to summarize, my question is: how can I create a collection of functions that can be used both in a sketch and in a library for Arduino?

6

You need to "split" your library.

Placing full functions inside a header file (.h) is bad form and causes the exact problem you are seeing. Every time you include the header file you create an entirely new copy of the function. This can only work if the functions are static, which means that they exist, and are contained entirely within, the function in which the header is included in. All outside access to them is completely cut off and they become "local" to the file. That means you can have multiple copies of them in one program. However that is wasteful of space since you are duplicating your code.

Instead you need to have the code itself in a .cpp file, which gets compiled separately and then linked with your sketch at the end of compilation, and just pointers to the functions you have written in your .h file.

Utilities.h:

extern void myFunction();

Utilities.cpp:

void myFunction() {
    blah blah
}

The .h file just contains a prototype for the functions which tells the compiler that "This function is defined elsewhere. Find it later on when you link."

It's only the .h file that is included in libraries and sketches, etc, so only the prototype that is duplicated between files. The .cpp is compiled separately and thus only compiled the once, so you don't get the code duplicated.

One caveat with this is that your sketch must include the library you have written so that the IDE knows to look for .cpp files within it to compile. And you must use #include <Utilities.h> for it to be able to work that out. Using a full path rather than just <Utilities.h> means that you break all portability and the IDE may not know to look for .cpp files in there, or even where to actually find it when compiling. Note as well that the IDE needs to be restarted after creating a new library, which is why it may not be able to find it in your experiments.

  • Thanks a lot, I thought that the format .h + .cpp was exclusively for classes. – tomph Dec 24 '16 at 12:40
  • No, the keyword class denotes a class. .h + .cpp is normal programming practice and procedure and has nothing at all to do with classes. You can create classes inside a .ino file if you want. – Majenko Dec 24 '16 at 12:41
  • What about the externkeyword? Is it essential? I never used it inside an header file while declaring methods of a class – tomph Dec 24 '16 at 12:43
  • It is not essential, no. It used to be required, but now it is entirely optional. I like to keep it in there as a reminder that "this function is implemented elsewhere". It is only required now for variables - functions have it implicitly automatically in modern compilers. – Majenko Dec 24 '16 at 12:44
  • Oh and class methods aren't external, they are part of a class. An "extern" function is a raw function, not a class member. they are very very different beasts. – Majenko Dec 24 '16 at 12:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.