Web IDE compile

I am trying to add support for a 4.2" BW EPaper display to an existing application that has already support for a 2.13" BW display. I am using the GxEPD2 library. I have separately built and tested applications targeted for each size of display and I am now trying to combine the files for each in the same application with conditional compilation to include the relevant files. However, when I add support for the 4.2" display (GxEPD2_420.h/.cpp) to the files and test the compile I am getting an error telling me these files were included and compiled which they should not have been. I have tried Clearing the cache. This is the raw error.

../build/target/user/platform-14-msrc/GxEPD2_420.o src/GxEPD2_420.cpp
In file included from src/GxEPD2_420.cpp:1:0:
src/GxEPD2_420.h:14:40: error: 'GDEW042T2' is not a member of 'GxEPD2'
     static const GxEPD2::Panel panel = GxEPD2::GDEW042T2;
../build/module.mk:277: recipe for target '../build/target/user/platform-14-msrc/GxEPD2_420.o' failed

This suggests that whatever I put in as conditional includes is being ignored and it gets included and compiled anyway? As soon as I remove the files it compiles fine. I noticed the same with another library - is there a way around this?

That’s to be expected.

Each module (individual implementation file) will be built independently - regardless of “it’s” header being included in another module or not.
An #include statement is just a proprocessor directive to “insert” the contents of the respective header file in place it. Commonly a header file would only provide the forward declarations for the following code to be compilable but the connection between forward declaration and its implementation would happen during linkage for which all potential object files need to be present already.

The proper way around the error would not be to exclude the files from the compile but to address the “missing member” issue itself.

Understood about the #include - good learning point.

If I include the .h/.cpp for the 4.2" display I can get it to build for the 2.13" display but not for the 4.2" display. Understanding the compiler errors is beyond my C++ level - abstract parameters and virtual functions - any pointers as to what I am missing gratefully received.

In file included from mesh-endnode-base.ino:96:0:
src/GxEPD2_BW.h: In instantiation of 'class GxEPD2_BW<GxEPD2_420, 300u>':
mesh-endnode-base.ino:101:61:   required from here
src/GxEPD2_BW.h:14:5: error: invalid abstract parameter type 'GxEPD2_420'
     GxEPD2_BW(GxEPD2_Type epd2_instance) : Adafruit_GFX(GxEPD2_Type::WIDTH, GxEPD2_Type::HEIGHT), epd2(epd2_instance)
In file included from mesh-endnode-base.ino:95:0:
src/GxEPD2_420.h:8:7: note:   because the following virtual functions are pure within 'GxEPD2_420':
 class GxEPD2_420 : public GxEPD2_EPD
In file included from src/GxEPD2_420.h:6:0,
                 from mesh-endnode-base.ino:95:
src/GxEPD2_EPD.h:45:18: note: 	virtual void GxEPD2_EPD::hibernate()
     virtual void hibernate() = 0; // turns powerOff() and sets controller to deep sleep for minimum power use, ONLY if wakeable by RST (rst >= 0)
In file included from mesh-endnode-base.ino:96:0:
src/GxEPD2_BW.h:13:17: error: cannot declare field 'GxEPD2_BW<GxEPD2_420, 300u>::epd2' to be of abstract type 'GxEPD2_420'
     GxEPD2_Type epd2;
mesh-endnode-base.ino:101:111: error: invalid cast to abstract class type 'GxEPD2_420'

This is the GxEPD2_BW.h file excerpt.

#include <Adafruit_GFX_RK.h>
#include "gfxfont.h"
#include "GxEPD2_EPD.h"
//#include "GxEPD2_213_B72.h"
#include "GxEPD2_420.h"

template<typename GxEPD2_Type, const uint16_t page_height>
class GxEPD2_BW : public Adafruit_GFX
    GxEPD2_Type epd2;
    GxEPD2_BW(GxEPD2_Type epd2_instance) : Adafruit_GFX(GxEPD2_Type::WIDTH, GxEPD2_Type::HEIGHT), epd2(epd2_instance)
      _page_height = page_height;
      _pages = (HEIGHT / _page_height) + ((HEIGHT % _page_height) > 0);
      _using_partial_mode = false;
      _current_page = 0;

This is a purely abstract function definition (indicated by = 0;) which will require any derived class to actually provide an implementation.
As long there are some abstract functions “unresolved” you cannot instantiate that class.

If you really don’t need that function you’d at least need to provide a stub

virtual void GxEPD2_420::hibernate() { }

Thanks. Stubbing hibernate() has at least cured the compile issue. Trouble is I don’t understand why JM Zing wrote the GxEPD2 library in this way. This isn’t the only function defined this way yet the others don’t appear to throw an error - possibly because the derived class provides an implementation? So maybe the real solution was to provide such an implementation in that class. I am at the edge or slightly beyond my understanding :thinking::confused:

That would go into the philosophy behind OOP and C++

  • the GxEPD2 class is only meant to define the common features (aka interface) all of the derived classes must support, but in itself will not actually implement any device
  • since the base class has no knowledge about the actual hardware capabilities or how to actaully talk to the hardware there is little use in providing a “dummy” implementation
  • since the base is not bound to any hardware preventing instantiating an object of that kind is a logical choice

Can’t answer that without an example.

BTW, there already seems to be a GxEPD2_420 implementation

Thanks for the explanation. The theory is one thing, understanding someone else’s implementation another! GxEDP2_420 - I am using a copy of that to drive the display.

Then I’m surprised you got the “pure abstract” error message since that code already features an implementation for hibernate() :confused:

Probably a previous version - I know JMZ has updated the libraries. I have been occupied with other things since I initially tried out the library for this display model.