I have a large project which I've split into multiple files, and now, for my first time, I want to move files into my project library so that I can branch my project. I've looked through instructions on how to do so on this message board and elsewhere.
But when I follow the instructions I've found, I get errors from calls to another included library. Here's what my code looks like:
RCfaces.h:
#ifndef _RCFACES_h
#define _RCFACES_h
#include "TFT_eSPI.h"
void showTitle_4Face(String title, int xoffs) ;
..... and so on
RCface.cpp:
#include "RCfaces.h"
#include "TFT_eSPI.h"
void showTitle_4Face(String title, int xoffs) {
tft.setTextColor(TFT_WHITE);
...and so on.
The error I get is:
"error: 'tft' was not declared in this scope
8 | tft.setTextColor(TFT_WHITE);"
This is code that was working fine when RCfaces was an .ino file. I'm sure I've made some kind of newbie error here but I've been unable to find an error in what seems like a very simple transform. Any help would be most welcome, thank you!
--- later note: I've now found the "extern" statement and am using that to include TFT_eSPI and other libraries, functions and variables. This seems to be working, although I have many extern statements to add so the final verdict is not yet in.
Assuming tft is not a local variable in the RCFace library, do you pass a reference to tft in the class' constructor? Libraries don't know about variables declared in your .ino file unless you tell them.
So I need to instantiate the tft object again in my library?
I've gotten past the problem with tft by using extern TFT_eSPI tft;
Now I'm having to do that for other externals, as I work my way through the errors. Is this the right way to do this?
Not again. If the intention is for the instantiation to be done in the sketch code, then it should only be done in the sketch code.
Doing it in the sketch can provide more flexibility. In this case, it would allow the sketch developer to define the dimensions of the display via the optional _W and _H parameters of the TFT_eSPI class constructor:
(though you could also provide an interface for configuration of the dimensions via your library's API)
In cases where the class inherits from a general purpose class, it is especially beneficial to allow the user to provide the object, as this way they can use any compatible object instead of the use of a specific class being hardcoded into the library. We typically do this with the standardized Print and Stream classes from the Arduino core API.
But in applications where there isn't any unique configurability in the constructor, and where only a single class type is usable, then it might be better to do the instantiation in the library code so that it doesn't need to be done in every sketch that uses the library.
No. Using globals to pass data from the sketch to the library is unintuitive for the user. The correct way to do it is to pass the data from the sketch to the library via parameters of the library's functions or constructors.
Thanks for this. I've been coding in C a long time, but never really got the hang of C++, esp. inheritance and constructors.
I understand what you've written about the right way to pass data; clearly I've got some work to do in adapting these functions to be usable as a library.
Thank you for your time and help, greatly appreciated.