Forward Declaration not working

Hey There! I’m working with the fastLED library and trying to use one of its functions: blur2d inside this function call to a second function [blurColumns] which in turn calls this third function XY( ). XY( ) is forward declaration for a function that I’ve written in my app. When I try to compile calls to the forward declaration by the library code come up as undefined references. Any ideas?

this links to the related code in the library:
line 356 is the forward declaration.
lines 415,420,421 are here the XY( ) function get called- these lines are

Here is my code:

#include "application.h"
#include "FastLED/FastLED.h"
FASTLED_USING_NAMESPACE;

#define MATRIX_WIDTH 11
#define MATRIX_HEIGHT 22
// How many leds in strip?
#define NUM_LEDS (MATRIX_WIDTH * MATRIX_HEIGHT)
#define DATA_PIN 0
// Define the array of leds
CRGB leds[NUM_LEDS];

//define some basic variables
int xPos=0, yPos=0, xSpd=1, ySpd=1;

void setup() { 
    FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);
}
void loop() { 
    //just ponging a pixel around my LED matrix.
    leds[XY(xPos,yPos)] = 0xFF6600;
    FastLED.show();
    delay(80);
    //This is the call giving me problems. It lives in colorutils.cpp at line 391.
    blur2d(leds,MATRIX_HEIGHT,MATRIX_WIDTH,100);
    FastLED.show();
    xPos+=xSpd;
    yPos+=ySpd;
    //bounce off the walls.
    if((xPos>=MATRIX_WIDTH-1) || (xPos<=0)){
        xSpd*=-1;
    }
    if((yPos>=MATRIX_HEIGHT-1)||(yPos<=0) ){
        ySpd*=-1;
    }
}

//this function is required by a forward declaration in colorutils.cpp at line 358 but currently that isn't working... 
uint16_t XY( uint8_t x, uint8_t y) {
    uint16_t i;
    if( x & 0x01) {
      // Odd columns run down
      uint8_t reverseY = (MATRIX_HEIGHT - 1) - y;
      i = (x * MATRIX_HEIGHT) + reverseY;
    } else {
      // Even columns run up
      i = (x * MATRIX_HEIGHT) + y;
    }
    if(i<0){
        i=0;
    }
    return i;
}

here is the error that gets thrown:

FastLED/FastLED.h:12:2: warning: #warning FastLED version 3001000 (Not really a warning, just telling you here.) [-Wcpp]
 #warning FastLED version 3001000  (Not really a warning, just telling you here.)
  ^
../../../build/target/user/platform-6/libuser.a(colorutils.o): In function `NSFastLED::blurColumns(NSFastLED::CRGB*, unsigned char, unsigned char, unsigned char)':
FastLED/colorutils.cpp:417: undefined reference to `NSFastLED::XY(unsigned char, unsigned char)'
FastLED/colorutils.cpp:422: undefined reference to `NSFastLED::XY(unsigned char, unsigned char)'
FastLED/colorutils.cpp:423: undefined reference to `NSFastLED::XY(unsigned char, unsigned char)'
collect2: error: ld returned 1 exit status
make: *** [bd20f0566bb2c40784ba1fd35ca17b9694d7c784c3607de23c15c7304a6d.elf] Error 1


  [1]: https://github.com/FastLED/FastLED/blob/master/colorutils.cpp

you might try adding #pragma SPARK_NO_PREPROCESSOR and add the forwarding manually.

1 Like

Ah - the problem is that XY is a function declared extern/weak inside of colorutils.cpp - inside the NSFastLED namespace. Which means that if you want to use it on the sparkcore, you need to wrap the definition of XY with FASTLED_NAMESPACE_BEGIN/FASTLED_NAMESPACE_END:

FASTLED_NAMESPACE_BEGIN
uint16_t XY(uint8_t x, uint8_t y) { 
    ...
}
FASTLED_NAMESPACE_END
1 Like

So, I’m officially way our of my league here and have some reading up to do but… I tried The FASTLED_NAMESPACE_BEGIN/FASTLED_NAMESPACE_END you suggested and found a new error:

FastLED/led_sysdefs_arm_stm32.h:7:31: error: expected '}' at end of input
#define FASTLED_NAMESPACE_END }
                           ^

Looking at the code led_sysdefs_arm_stm32.h I see:

6. #define FASTLED_NAMESPACE_BEGIN namespace NSFastLED {
7. #define FASTLED_NAMESPACE_END }
8. #define FASTLED_USING_NAMESPACE using namespace NSFastLED;

This differs from the similarly named led_sysdefs.h where I find these #defines:

#ifndef FASTLED_NAMESPACE_BEGIN
#define FASTLED_NAMESPACE_BEGIN
#define FASTLED_NAMESPACE_END
#define FASTLED_USING_NAMESPACE
#endif

No idea what this all means…

That is because the spark platform is the only one that requires everything for FastLED to be in its own namespace.

Where did you put my suggested changes?

Here is what I needed to do to get your code to compile (sadly - Particle’s preprocessor isn’t intelligent enough to handle moving a prototype that’s inside of a namespace properly):

#pragma SPARK_NO_PREPROCESSOR

#include "application.h"
#include "FastLED/FastLED.h"
FASTLED_USING_NAMESPACE;

#define MATRIX_WIDTH 11
#define MATRIX_HEIGHT 22
// How many leds in strip?
#define NUM_LEDS (MATRIX_WIDTH * MATRIX_HEIGHT)
#define DATA_PIN 0
// Define the array of leds
CRGB leds[NUM_LEDS];

//define some basic variables
int xPos=0, yPos=0, xSpd=1, ySpd=1;

//this function is required by a forward declaration in colorutils.cpp at line 358 but currently that isn't working... 
FASTLED_NAMESPACE_BEGIN
uint16_t XY( uint8_t x, uint8_t y) {
    uint16_t i;
    if( x & 0x01) {
      // Odd columns run down
      uint8_t reverseY = (MATRIX_HEIGHT - 1) - y;
      i = (x * MATRIX_HEIGHT) + reverseY;
    } else {
      // Even columns run up
      i = (x * MATRIX_HEIGHT) + y;
    }
    if(i<0){
        i=0;
    }
    return i;
}
FASTLED_NAMESPACE_END

void setup() { 
    FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);
}
void loop() { 
    //just ponging a pixel around my LED matrix.
    leds[XY(xPos,yPos)] = 0xFF6600;
    FastLED.show();
    delay(80);
    //This is the call giving me problems. It lives in colorutils.cpp at line 391.
    blur2d(leds,MATRIX_HEIGHT,MATRIX_WIDTH,100);
    FastLED.show();
    xPos+=xSpd;
    yPos+=ySpd;
    //bounce off the walls.
    if((xPos>=MATRIX_WIDTH-1) || (xPos<=0)){
        xSpd*=-1;
    }
    if((yPos>=MATRIX_HEIGHT-1)||(yPos<=0) ){
        ySpd*=-1;
    }
}
1 Like

Ahhh, I’d had unimplemented the “#pragma SPARK_NO_PREPROCESSOR” line up top. Put it in. Fixed some of my own silly code and- YAY! Blur Joy!

In case anyone finds themselves here I’m including the final code I got working. This is an LED matrix that runs up and down by columns in a serpentine pattern where LED 0 is bottom Left corner off pin D0. It seems most implementations assume rows so you’ll find in 2D blur I send height where width would go and vise versa. Anyway. Cribed, cribbed, cribbed code- decent place to start…

#pragma SPARK_NO_PREPROCESSOR

#include "application.h"
#include "FastLED/FastLED.h"
FASTLED_USING_NAMESPACE;

#define MATRIX_WIDTH 11
#define MATRIX_HEIGHT 22
// How many leds in your strip?
#define NUM_LEDS (MATRIX_WIDTH * MATRIX_HEIGHT)

FASTLED_NAMESPACE_BEGIN
uint16_t XY( uint8_t x, uint8_t y) {
    uint16_t i;
    if( x & 0x01) {
      // Odd rows run backwards
      uint8_t reverseY = (MATRIX_HEIGHT - 1) - y;
      i = (x * MATRIX_HEIGHT) + reverseY;
    } else {
      // Even rows run forwards
      i = (x * MATRIX_HEIGHT) + y;
    }
  if(i<0){
      i=0;
  }
  return i;
}
FASTLED_NAMESPACE_END

// For led chips like Neopixels, which have a data line, ground, and power, you just
// need to define DATA_PIN.  For led chipsets that are SPI based (four wires - data, clock,
// ground, and power), like the LPD8806 define both DATA_PIN and CLOCK_PIN
    #define DATA_PIN 0
int xPos1=0;
int yPos1=0;
int xPos2=10;
int yPos2=5;
int xSpd1=1;
int ySpd1=3;
int xSpd2=-1;
int ySpd2=1;

// Define the array of leds
CRGB leds[NUM_LEDS];

void setup() { 
  	  FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);
}
void loop() { 
  // Turn the LED on, then pause
  //leds[XY(xPos1,yPos1)] = CRGB::Orange;
   leds[XY(xPos1,yPos1)] = 0xFF6600;
 leds[XY(xPos2,yPos2)] = 0xFF0066;
 //blur1d(leds,NUM_LEDS,100);
 blur2d(leds,MATRIX_WIDTH,MATRIX_HEIGHT,100);
  FastLED.show();
  delay(90);
  // Now turn the LED off, then pause
  //leds[XY(xPos,yPos)] = CRGB::Black;

blur1d(leds,NUM_LEDS,150);
 // blur2d(leds,22,11,100);
  FastLED.show();
  xPos1+=xSpd1;
  yPos1+=ySpd1;
  if((xPos1>=MATRIX_WIDTH-1) || (xPos1<=0)){
      xSpd1*=-1;
  }
  //
  //
  if(yPos1>=MATRIX_HEIGHT-1){
      ySpd1*=-1;
      yPos1=MATRIX_HEIGHT-1;
  }
    if(yPos1<=0){
      ySpd1*=-1;
       yPos1=1;
  }
  //
  //
    xPos2+=xSpd2;
  yPos2+=ySpd2;
  if((xPos2>=MATRIX_WIDTH-1) || (xPos2<=0)){
      xSpd2*=-1;
  }
  if((yPos2>=MATRIX_HEIGHT-1)||(yPos2<=0) ){
      ySpd2*=-1;
  }
}
1 Like