Invalid cast to abstract class type 'Adafruit_ILI9341'

Ok. I’ve had 2 pairs of programmer eyes. Only one pair is autistic. Can’t see why it won’t make an instance of this class.

Adafruit_ILI9341 tft = Adafruit_ILI9341(tftcspin, tftrspin);

gets me the error message.

The class is defined in ILI9341.h as:

class Adafruit_ILI9341 : public Adafruit_SPITFT {
    public:
        Adafruit_ILI9341(int8_t _CS, int8_t _DC, int8_t _MOSI, int8_t _SCLK, int8_t _RST = -1, int8_t _MISO = -1);
        Adafruit_ILI9341(int8_t _CS, int8_t _DC, int8_t _RST = -1);

        void    begin(uint32_t freq=0);
        void    setRotation(uint8_t r);
        void    invertDisplay(boolean i);
        void    scrollTo(uint16_t y);

        // Transaction API not used by GFX
        void    setAddrWindow(uint16_t x, uint16_t y, uint16_t w, uint16_t h);

        uint8_t readcommand8(uint8_t reg, uint8_t index=0);
};

To see that it was including that .h, I put an x inside public and got a gazillion error messages, as expected. I tried replacing tftrspin and tftcspin with literals, with no result. I copy/pasted the class name from the .h file just to be sure I didn’t have it misspelled.

Can any of you non-crosseyed programmers spot my blunder?

I just looked. The clipped line IS complete:

Adafruit_ILI9341(int8_t _CS, int8_t _DC, int8_t _MOSI, int8_t _SCLK, int8_t _RST = -1, int8_t _MISO = -1);

And the raw says:

Processing  tftdisplayd.ino
make -C ../modules/electron/user-part all
make[1]: Entering directory '/firmware/modules/electron/user-part'
make -C ../../../user 
make[2]: Entering directory '/firmware/user'
Building cpp file: tftdisplayd.cpp
Invoking: ARM GCC CPP Compiler
mkdir -p ../build/target/user/platform-10-m
arm-none-eabi-gcc -DSTM32_DEVICE -DSTM32F2XX -DPLATFORM_THREADING=1 -DPLATFORM_ID=10 -DPLATFORM_NAME=electron -DUSBD_VID_SPARK=0x2B04 -DUSBD_PID_DFU=0xD00A -DUSBD_PID_CDC=0xC00A -DSPARK_PLATFORM -g3 -gdwarf-2 -Os -mcpu=cortex-m3 -mthumb -DINCLUDE_PLATFORM=1 -DPRODUCT_ID=10 -DPRODUCT_FIRMWARE_VERSION=65535 -DUSE_STDPERIPH_DRIVER -DDFU_BUILD_ENABLE -DSYSTEM_VERSION_STRING=0.8.0-rc.12 -DRELEASE_BUILD -I./inc -I../wiring/inc -I../system/inc -I../services/inc -I../services/nanopb -I../communication/src -I../hal/inc -I../hal/shared -I/rtos/FreeRTOSv8.2.2/FreeRTOS/Source/include -I/rtos/FreeRTOSv8.2.2/FreeRTOS/Source/portable/GCC/ARM_CM3 -I../hal/src/electron -I../hal/src/stm32f2xx -I../hal/src/stm32 -I../platform/shared/inc -I../platform/MCU/STM32F2xx/STM32_USB_Host_Driver/inc -I../platform/MCU/STM32F2xx/STM32_StdPeriph_Driver/inc -I../platform/MCU/STM32F2xx/STM32_USB_OTG_Driver/inc -I../platform/MCU/STM32F2xx/STM32_USB_Device_Driver/inc -I../platform/MCU/STM32F2xx/SPARK_Firmware_Driver/inc -I../platform/MCU/shared/STM32/inc -I../platform/MCU/STM32F2xx/CMSIS/Include -I../platform/MCU/STM32F2xx/CMSIS/Device/ST/Include -I../dynalib/inc -I -I./libraries -I. -MD -MP -MF ../build/target/user/platform-10-mtftdisplayd.o.d -ffunction-sections -fdata-sections -Wall -Wno-switch -Wno-error=deprecated-declarations -fmessage-length=0 -fno-strict-aliasing -DSPARK=1 -DPARTICLE=1 -Wundef -DSTART_DFU_FLASHER_SERIAL_SPEED=14400 -DSTART_YMODEM_FLASHER_SERIAL_SPEED=28800 -DSPARK_PLATFORM_NET=UBLOXSARA -fno-builtin-malloc -fno-builtin-free -fno-builtin-realloc  -DLOG_INCLUDE_SOURCE_INFO=1 -DPARTICLE_USER_MODULE -DUSER_FIRMWARE_IMAGE_SIZE=0x20000 -DUSER_FIRMWARE_IMAGE_LOCATION=0x8080000 -DMODULAR_FIRMWARE=1 -DMODULE_VERSION=5 -DMODULE_FUNCTION=5 -DMODULE_INDEX=1 -DMODULE_DEPENDENCY=4,2,311 -DMODULE_DEPENDENCY2=0,0,0 -D_WINSOCK_H -D_GNU_SOURCE -DLOG_MODULE_CATEGORY="\"app\""  -fno-exceptions -fno-rtti -fcheck-new -std=gnu++11 -c -o ../build/target/user/platform-10-mtftdisplayd.o tftdisplayd.cpp
tftdisplayd.ino:19:59: error: invalid cast to abstract class type 'Adafruit_ILI9341'
 Adafruit_ILI9341 tft = Adafruit_ILI9341(tftcspin, tftrspin);
                                                           ^
In file included from tftdisplayd.ino:5:0:
ILI9341.h:135:7: note:   because the following virtual functions are pure within 'Adafruit_ILI9341':
 class Adafruit_ILI9341 : public Adafruit_SPITFT {
       ^
In file included from ../wiring/inc/spark_wiring_string.h:34:0,
                 from ../wiring/inc/spark_wiring_stream.h:30,
                 from ../wiring/inc/spark_wiring.h:38,
                 from ./inc/application.h:40,
                 from tftdisplayd.cpp:1:
../wiring/inc/spark_wiring_print.h:63:20: note: 	virtual size_t Print::write(uint8_t)
     virtual size_t write(uint8_t) = 0;
                    ^
tftdisplayd.ino:19:18: error: cannot declare variable 'tft' to be of abstract type 'Adafruit_ILI9341'
 Adafruit_ILI9341 tft = Adafruit_ILI9341(tftcspin, tftrspin);
                  ^
tftdisplayd.ino: In function 'void setup()':
tftdisplayd.ino:24:13: error: 'tstcspin' was not declared in this scope
     pinMode(tstcspin,OUTPUT);
             ^
tftdisplayd.ino:28:5: error: expected ';' before 'tft'
     tft.Begin();
     ^
../build/module.mk:265: recipe for target '../build/target/user/platform-10-mtftdisplayd.o' failed
make[2]: Leaving directory '/firmware/user'
make[2]: *** [../build/target/user/platform-10-mtftdisplayd.o] Error 1
../../../build/recurse.mk:11: recipe for target 'user' failed
make[1]: Leaving directory '/firmware/modules/electron/user-part'
make[1]: *** [user] Error 2
../build/recurse.mk:11: recipe for target 'modules/electron/user-part' failed
make: *** [modules/electron/user-part] Error 2

Although this syntax often seen, it's not best practice.

Adafruit_ILI9341 tft = Adafruit_ILI9341(tftcspin, tftrspin);

What this does is that it instantiates two objects - one default (Adafruit_ILI0341 tft) and a second one which you actually wane - and then second one is assigned to the the object variable replacing the default version.
Apart from extra work, some classes don't feature a public default constructor.

Hence the prefered syntax would be

Adafruit_ILI9341 tft(tftcspin, tftrspin); 

since this only creates the one object you want in place.


Which clipped line?
The code block window has a scroll bar :wink:

1 Like

Oh, that makes sense. Got it straight from adafruit’s github. “Correct syntax is left as an exercise for the student.”

Adafruit_ILI9341 tft(tftcspin, tftrspin);

But now it says: cannot declare variable ‘tft’ to be of abstract type ‘Adafruit_ILI9341’ I think the raw indicates there’s something it doesn’t like in the SPITFT code?

And the raw says:

Processing  tftdisplayd.ino
make -C ../modules/electron/user-part all
make[1]: Entering directory '/firmware/modules/electron/user-part'
make -C ../../../user 
make[2]: Entering directory '/firmware/user'
Building cpp file: tftdisplayd.cpp
Invoking: ARM GCC CPP Compiler
mkdir -p ../build/target/user/platform-10-m
arm-none-eabi-gcc -DSTM32_DEVICE -DSTM32F2XX -DPLATFORM_THREADING=1 -DPLATFORM_ID=10 -DPLATFORM_NAME=electron -DUSBD_VID_SPARK=0x2B04 -DUSBD_PID_DFU=0xD00A -DUSBD_PID_CDC=0xC00A -DSPARK_PLATFORM -g3 -gdwarf-2 -Os -mcpu=cortex-m3 -mthumb -DINCLUDE_PLATFORM=1 -DPRODUCT_ID=10 -DPRODUCT_FIRMWARE_VERSION=65535 -DUSE_STDPERIPH_DRIVER -DDFU_BUILD_ENABLE -DSYSTEM_VERSION_STRING=0.8.0-rc.12 -DRELEASE_BUILD -I./inc -I../wiring/inc -I../system/inc -I../services/inc -I../services/nanopb -I../communication/src -I../hal/inc -I../hal/shared -I/rtos/FreeRTOSv8.2.2/FreeRTOS/Source/include -I/rtos/FreeRTOSv8.2.2/FreeRTOS/Source/portable/GCC/ARM_CM3 -I../hal/src/electron -I../hal/src/stm32f2xx -I../hal/src/stm32 -I../platform/shared/inc -I../platform/MCU/STM32F2xx/STM32_USB_Host_Driver/inc -I../platform/MCU/STM32F2xx/STM32_StdPeriph_Driver/inc -I../platform/MCU/STM32F2xx/STM32_USB_OTG_Driver/inc -I../platform/MCU/STM32F2xx/STM32_USB_Device_Driver/inc -I../platform/MCU/STM32F2xx/SPARK_Firmware_Driver/inc -I../platform/MCU/shared/STM32/inc -I../platform/MCU/STM32F2xx/CMSIS/Include -I../platform/MCU/STM32F2xx/CMSIS/Device/ST/Include -I../dynalib/inc -I -I./libraries -I. -MD -MP -MF ../build/target/user/platform-10-mtftdisplayd.o.d -ffunction-sections -fdata-sections -Wall -Wno-switch -Wno-error=deprecated-declarations -fmessage-length=0 -fno-strict-aliasing -DSPARK=1 -DPARTICLE=1 -Wundef -DSTART_DFU_FLASHER_SERIAL_SPEED=14400 -DSTART_YMODEM_FLASHER_SERIAL_SPEED=28800 -DSPARK_PLATFORM_NET=UBLOXSARA -fno-builtin-malloc -fno-builtin-free -fno-builtin-realloc  -DLOG_INCLUDE_SOURCE_INFO=1 -DPARTICLE_USER_MODULE -DUSER_FIRMWARE_IMAGE_SIZE=0x20000 -DUSER_FIRMWARE_IMAGE_LOCATION=0x8080000 -DMODULAR_FIRMWARE=1 -DMODULE_VERSION=5 -DMODULE_FUNCTION=5 -DMODULE_INDEX=1 -DMODULE_DEPENDENCY=4,2,311 -DMODULE_DEPENDENCY2=0,0,0 -D_WINSOCK_H -D_GNU_SOURCE -DLOG_MODULE_CATEGORY="\"app\""  -fno-exceptions -fno-rtti -fcheck-new -std=gnu++11 -c -o ../build/target/user/platform-10-mtftdisplayd.o tftdisplayd.cpp
tftdisplayd.ino:19:18: error: cannot declare variable 'tft' to be of abstract type 'Adafruit_ILI9341'
 Adafruit_ILI9341 tft(tftcspin, tftrspin);
                  ^
In file included from tftdisplayd.ino:5:0:
ILI9341.h:135:7: note:   because the following virtual functions are pure within 'Adafruit_ILI9341':
 class Adafruit_ILI9341 : public Adafruit_SPITFT {
       ^
In file included from ../wiring/inc/spark_wiring_string.h:34:0,
                 from ../wiring/inc/spark_wiring_stream.h:30,
                 from ../wiring/inc/spark_wiring.h:38,
                 from ./inc/application.h:40,
                 from tftdisplayd.cpp:1:
../wiring/inc/spark_wiring_print.h:63:20: note: 	virtual size_t Print::write(uint8_t)
     virtual size_t write(uint8_t) = 0;
                    ^
../build/module.mk:265: recipe for target '../build/target/user/platform-10-mtftdisplayd.o' failed
make[2]: Leaving directory '/firmware/user'
make[2]: *** [../build/target/user/platform-10-mtftdisplayd.o] Error 1
../../../build/recurse.mk:11: recipe for target 'user' failed
make[1]: Leaving directory '/firmware/modules/electron/user-part'
make[1]: *** [user] Error 2
../build/recurse.mk:11: recipe for target 'modules/electron/user-part' failed
make: *** [modules/electron/user-part] Error 2

I’m not sure why that’s happening, but I do have a port of that library that I know works correctly on the Particle platform. It’s Adafruit_ILI9341_RK in the community libraries and the instructions are here:

I tested it with the Adafruit 2.4" 320x240 touchscreen FeatherWing and mesh devices, but it should work with any device and other touchscreen displays with the same chipset.

2 Likes

This would suggest that there is some function that needs to be overridden (since it's abstract in the base class) but isn't.

Where did you have that library from? Got a link?

Rickkas, I just grabbed your library. Thanks.

Still get the error where I try to use the class. I wonder, like ScruffR, if there is some method I need to override but haven’t.

Here’s where I got my library: https://github.com/adafruit/Adafruit-GFX-Library

And I built the SPITFT_Macros.h like so:

#ifndef _ADAFRUIT_SPITFT_MACROS
#define _ADAFRUIT_SPITFT_MACROS

#include "Particle.h"

#define tftrstpin   C0
#define tftrspin    C1
#define tftcspin    D5

#define tftrstlow digitalWriteFast(tftrstpin, LOW)
#define tftrsthigh digitalWriteFast(tftrstpin, HIGH)
#define tftrslow digitalWriteFast(tftrspin, LOW)
#define tftrshigh digitalWriteFast(tftrspin, HIGH)
#define tftcslow digitalWrite(tftcspin, LOW)
#define tftcshigh digitalWriteFast(tftcspin, HIGH)

#define tftSPIinit SPI1.begin(SPI_MODE_MASTER)
#define tftSPIspeed SPI1.setClockSpeed(1, MHZ)
/*
 * Control Pins
 * */

#define SPI_DC_HIGH()       digitalWriteFast(tftrspin,HIGH)
#define SPI_DC_LOW()        digitalWriteFast(tftrspin,LOW)
#define SPI_CS_HIGH()       digitalWriteFast(tftcspin,HIGH)
#define SPI_CS_LOW()        digitalWriteFast(tftcspin,LOW)

/*
 * Hardware SPI Macros
 * */

#define SPI_SET_CLOCK()    SPI1.setClockSpeed(1, MHZ)
#define SPI_BEGIN_TRANSACTION() SPI1.begin(SPI_MODE_MASTER)
#define SPI_READ()              SPI1.transfer(0)
#define SPI_WRITE(b)            SPI1.transfer(b)
#define SPI_WRITE16(s)          SPI1.transfer(s>>8); SPI1.transfer(s)
#define SPI_WRITE32(l)          SPI1.transfer(l>>24); SPI1.transfer(l>>16); SPI1.transfer(l>>8); SPI1.transfer(l)
#define SPI_WRITE_PIXELS(c,l)   for(int i=0; i<(l); i+=2){ HSPI_WRITE(c[i+1]); HSPI_WRITE(c[i]); }


#endif // _ADAFRUIT_SPITFT_MACROS

This says that Adafruit_ILI9341 inherits from Adafruit_SPITFT. The error you are getting is that the constructor for the LIL9341 specific class is still pure virtual, which means that there is no implementation code for it or the class it it inherits from.

Do you also have the .h/.cpp files for Adafruit_SPITFT in your project?

Oh, THAT's what that means!

Strangely, my SPITFT.cpp (spit fit) seems to contain definitions, but no code. Looks more like a .h.

That's what abstract means in C++ jargon.
Usually the definition looks like

 virtual void someAbstract() = 0;

And this means that any derived class has to implement that function.

1 Like

So, I fetched Adafruit_SPITFT.cpp from https://github.com/adafruit/Adafruit-GFX-Library and made sure it was in and …

…same error.

I don’t think it’s compiling my spitft.cpp. I edited the code to look like:

Adafruit_SPITFT::Adafruit_SPITFT(uint16_t w, uint16_t h,
				 int8_t cs, int8_t dc, int8_t rst) 
  : Adafruit_SPITFT(w, h, &SPI, cs, dc, rst) 
{
  // We just call the hardware SPI instantiator with the default SPI device (&SPI)
}

The Royal Nonesuch


And this should raise some major errors, but it does not. Should I not see SPITFT.cpp mentioned in the raw, especially since I made it syntactically incorrect?

Processing  tftdisplayd.ino
make -C ../modules/electron/user-part all
make[1]: Entering directory '/firmware/modules/electron/user-part'
make -C ../../../user 
make[2]: Entering directory '/firmware/user'
Building cpp file: tftdisplayd.cpp
Invoking: ARM GCC CPP Compiler
mkdir -p ../build/target/user/platform-10-m
arm-none-eabi-gcc -DSTM32_DEVICE -DSTM32F2XX -DPLATFORM_THREADING=1 -DPLATFORM_ID=10 -DPLATFORM_NAME=electron -DUSBD_VID_SPARK=0x2B04 -DUSBD_PID_DFU=0xD00A -DUSBD_PID_CDC=0xC00A -DSPARK_PLATFORM -g3 -gdwarf-2 -Os -mcpu=cortex-m3 -mthumb -DINCLUDE_PLATFORM=1 -DPRODUCT_ID=10 -DPRODUCT_FIRMWARE_VERSION=65535 -DUSE_STDPERIPH_DRIVER -DDFU_BUILD_ENABLE -DSYSTEM_VERSION_STRING=0.8.0-rc.12 -DRELEASE_BUILD -I./inc -I../wiring/inc -I../system/inc -I../services/inc -I../services/nanopb -I../communication/src -I../hal/inc -I../hal/shared -I/rtos/FreeRTOSv8.2.2/FreeRTOS/Source/include -I/rtos/FreeRTOSv8.2.2/FreeRTOS/Source/portable/GCC/ARM_CM3 -I../hal/src/electron -I../hal/src/stm32f2xx -I../hal/src/stm32 -I../platform/shared/inc -I../platform/MCU/STM32F2xx/STM32_USB_Host_Driver/inc -I../platform/MCU/STM32F2xx/STM32_StdPeriph_Driver/inc -I../platform/MCU/STM32F2xx/STM32_USB_OTG_Driver/inc -I../platform/MCU/STM32F2xx/STM32_USB_Device_Driver/inc -I../platform/MCU/STM32F2xx/SPARK_Firmware_Driver/inc -I../platform/MCU/shared/STM32/inc -I../platform/MCU/STM32F2xx/CMSIS/Include -I../platform/MCU/STM32F2xx/CMSIS/Device/ST/Include -I../dynalib/inc -I -I./libraries -I. -MD -MP -MF ../build/target/user/platform-10-mtftdisplayd.o.d -ffunction-sections -fdata-sections -Wall -Wno-switch -Wno-error=deprecated-declarations -fmessage-length=0 -fno-strict-aliasing -DSPARK=1 -DPARTICLE=1 -Wundef -DSTART_DFU_FLASHER_SERIAL_SPEED=14400 -DSTART_YMODEM_FLASHER_SERIAL_SPEED=28800 -DSPARK_PLATFORM_NET=UBLOXSARA -fno-builtin-malloc -fno-builtin-free -fno-builtin-realloc  -DLOG_INCLUDE_SOURCE_INFO=1 -DPARTICLE_USER_MODULE -DUSER_FIRMWARE_IMAGE_SIZE=0x20000 -DUSER_FIRMWARE_IMAGE_LOCATION=0x8080000 -DMODULAR_FIRMWARE=1 -DMODULE_VERSION=5 -DMODULE_FUNCTION=5 -DMODULE_INDEX=1 -DMODULE_DEPENDENCY=4,2,311 -DMODULE_DEPENDENCY2=0,0,0 -D_WINSOCK_H -D_GNU_SOURCE -DLOG_MODULE_CATEGORY="\"app\""  -fno-exceptions -fno-rtti -fcheck-new -std=gnu++11 -c -o ../build/target/user/platform-10-mtftdisplayd.o tftdisplayd.cpp
tftdisplayd.ino:19:18: error: cannot declare variable 'tft' to be of abstract type 'Adafruit_ILI9341'
 Adafruit_ILI9341 tft(tftcspin, tftrspin);
                  ^
In file included from tftdisplayd.ino:5:0:
ILI9341.h:131:7: note:   because the following virtual functions are pure within 'Adafruit_ILI9341':
 class Adafruit_ILI9341 : public Adafruit_SPITFT {
       ^
In file included from ../wiring/inc/spark_wiring_string.h:34:0,
                 from ../wiring/inc/spark_wiring_stream.h:30,
                 from ../wiring/inc/spark_wiring.h:38,
                 from ./inc/application.h:40,
                 from tftdisplayd.cpp:1:
../wiring/inc/spark_wiring_print.h:63:20: note: 	virtual size_t Print::write(uint8_t)
     virtual size_t write(uint8_t) = 0;
                    ^
../build/module.mk:265: recipe for target '../build/target/user/platform-10-mtftdisplayd.o' failed
make[2]: *** [../build/target/user/platform-10-mtftdisplayd.o] Error 1
make[2]: Leaving directory '/firmware/user'
../../../build/recurse.mk:11: recipe for target 'user' failed
make[1]: *** [user] Error 2
make[1]: Leaving directory '/firmware/modules/electron/user-part'
../build/recurse.mk:11: recipe for target 'modules/electron/user-part' failed
make: *** [modules/electron/user-part] Error 2

The function that needs to be implemented to make the class instantiable (non-abstract) is virtual size_t Adafruit_ILI9341::write(uint8_t) (as stated in the error note).

I can’t find any evidence that it’s compiling my SPITFT.cpp file. Curious. I think I’ll try an export all these files to a zip and build a new application from them. Not unusual for someone new to a programming environment to get the project bollixed up to the point the compiler is confused.

So, I scrapped the idea of adapting a downloaded library and built one. Perhaps I’ll upload it somewhere when it’s done and a little cleaned up.

1 Like