[SOLVED] Understanding OOP library & multi-files

I am trying to understand how to access a library function from multiple files.

Just unzip the attached files to a folder named low. They will compile just fine as-is, but if you uncomment the //#include "file_2.h" in the low.ino file. it gets an error, 'LL' does not name a type.

My question is, what do I need to do to access the LL.writeCommand from multiple files?

low.zip (1.08 KB)

Once you #include <library> or #include "library", you will be able to make calls to public functions (and variables) contained in those libraries.

The former #include statement (with angle brackets) and and latter #include statements (with quotes) determine the directory hierarchy through which the processor searches for that library. More on that here here.

PickyBiker:
... but if you uncomment the //#include "file_2.h" in the low.ino file. it gets an error, 'LL' does not name a type.

This sounds a lot like a syntax error. Can you post the code segment (and the code file) where that error appears?

PickyBiker:
My question is, what do I need to do to access the LL.writeCommand from multiple files?

file_2.h is a header file. You can only make declarations in a header file. You're attempting to make a function call with an undeclared object, LL.

Here's a cool aside that helped me out: what to put in a header/cpp file

If you specify a source file, file_2.cpp, and you have #include "file_2.h" included (which includes low_level.h), then you can make a function in file_2.cpp that can call a function from low_level.h.

file_2.h

#ifndef FILE_2_H
#define FILE_2_H

#include "low_level.h"


void foo(u8* cmd, u8 cCount); 


#endif

//LL.writeCommand(cmd, cCount); //Syntax error.

file_2.cpp

#include "file_2.h"

//Need to declare a LOW_LEVEL object if you wish to use its member function "writeCommand"

LOW_LEVEL obj1;  //This is global.

void foo(u8* cmd, u8 cCount)
{
        //LOW_LEVEL obj1; //This is local. You can also pass it as a parameter.
	obj1.writeCommand(cmd, cCount); //Using object 'obj1', which has global scope. 
}

This sounds a lot like a syntax error. Can you post the code segment (and the code file) where that error appears?

I posted all 4 files in a .zip

Okay, I think I'm a little closer.

Just a note: I am aware of the difference between includes using < and ". In the attached updated files, all includes use the " to facilitate programming. It's the only way I know how to develop the library files and the sketch that will use them at the same time. If there is a better way, I am open to that.
This looks closer to me , but still getting errors.

I created a file-2.h for the foo definition and put the actual foo function in the .cpp file. Now the obj1 appears to be undeclared.

What else is missing?

low.zip (1.44 KB)

obj1 is delcared in file_2.cpp with the comment "this is global".

It's only global within that file. How do you expect the main program to access variables private to the libraries? If it's declared in file_2.h, which you #included in the main file, then it is available to the main file. The two C++ files share the declarations (and access to the objects) via the header.

You may also look up the use of the extern keyword, but every time I use it, I feel like I'm covering up for a mistake. I've never been told, but I feel that it's a relic of C and should not appear in a C++ program.

I moved the declaration of obj1 to the file-2.h file and now a new error is 'class LOW_LEVEL' has no member named 'foo'. While I certainly understand that, I still don't know how to reach the original goal.

The goal is: The writeCommand function (which is in a library) needs to be called from multiple files.

In this particular case, I am trying to call it from low.ino and from file_2.cpp.

Note: The Adding of obj1 to the mix seems to have confused me even more.

Am I on the wrong approach here? Can someone successfully compile this and show me what is wrong?

PickyBiker:
I created a file-2.h for the foo definition and put the actual foo function in the .cpp file. Now the obj1 appears to be undeclared.

First:

I apologize for the bad comment. In foo.cpp, 'obj1' is not a global. It's local to that file (but visible to all functions in that .cpp file).

Also, note that 'obj1' is an instance of the class LOW_LEVEL, which you've defined in low_level.h. Therefore, it only knows of public functions from that class (namely writeCommand). This means you should not be using the dot-operator to call foo(). You can, however, call "obj1.writeCommand()" is a correct use of the invocation (dot) operator.

Second:

The function foo(), declared in foo.h and defined in foo.cpp is not a class member function (functions declared in a class are called class member function). It is a regular function, one that you otherwise could have defined in the file containing main(). Once you #include the header file in which the function appears, calling the function is sufficient.

Third:

If you want to use a LOWER_LEVEL object that's defined in another file, you must declare it as "extern" and make sure that it is defined in that other file.

Sketch:

#include "low_level.h"
#include "file_2.h"

extern LOW_LEVEL obj1; //"extern" is used to refer to the fact that obj1 is defined externally (outside)
                       //of this file, namely, in file_2.cpp
LOW_LEVEL LL;

void setup()
{
}

void loop()
{
  u8 cmd[10];
  u8 cCount = 5;

  LL.writeCommand(cmd, cCount);
  obj1.writeCommand(cmd, cCount); 
  foo(cmd, cCount); //foo() is not a member function of the LOWER_LEVEL class!
}

file_2.h

#include "low_level.h"

#ifndef FILE_2_H
#define FILE_2_H

extern LOW_LEVEL obj1;  //This is a declaration. Any file that #include file_2.h will know of obj1. 

void foo(u8* cmd, u8 cCount); 

#endif

file_2.cpp

//#include "low_level.h" //Unnecessary since you've #included it in file_2.h
#include "file_2.h"

LOW_LEVEL obj1;  //Definition of obj1. 

void foo(u8* cmd, u8 cCount)
{
  obj1.writeCommand(cmd, cCount); //Using object 'obj1', which has global scope.
}

Okay, success. Thank you very much for the help.

Now I will study the results to make sure I understand why parts were separated this way .cpp/.h/extern etc..

once again, thank you for the help.