Array an Klasse als static Klassenvariable übergeben - Linkerfehler

Hallo zusammen,

ich will ein Array aus der ino an eine Klasse in der .h per statischer Methode in eine statische Klassenvariable übergeben, um in den Instanzen damit zu arbeiten.
Der Kompiler ist friedlich, aber der Linker mault.
Wo ist mein Denkfehler?

die .ino:

#include <FastLED.h>
#include "BojeFastLed.h"

const uint16_t zeitIntervall = 250; // 1 Sekunde


const byte dataPin = 2;

// 1. Lednummer
// 2. Farbe
// 3. zum Anfang an/aus
// 4.-9. die Zeiten in zeitIntervallen! jeweils im Wechsel an/aus bzw. aus/an, je nach Startzustand. Nicht benötigte am Ende! weg lassen 
BojeFastLed bojen[] {
                {0, RED, 1, 12, 16, 10, 16, 4,40},
                {1, GREEN, 0, 8, 20},
                {2, BLUE, 1, 12, 20},
                {3, YELLOW, 1, 1, 1}
              };
const byte anzBojen = sizeof(bojen) / sizeof(bojen[0]);


CRGB leds[anzBojen];                                                            // <-- das Array

uint32_t lastMillis, zeitscheiben;

void runAll(uint32_t zeitscheibe) {
uint16_t geaendert = 0;
  for(byte i=0; i<anzBojen;i++) geaendert += bojen[i].run(zeitscheibe);
  // Nur wenn sich etwas geändert hat
  if (geaendert) FastLED.show();
}

void initAll() {
  for(byte i=0; i<anzBojen;i++) bojen[i].init();
  FastLED.show();
}

void setup() {
  Serial.begin(115200);
  Serial.println("Start Seezeichen");
  FastLED.addLeds<WS2812B, dataPin, GRB>(leds, anzBojen);
  FastLED.setBrightness(10);
  BojeFastLed::setCRGB(leds);                                              // <-- die Übergabe 
  initAll();
}           

void loop() {
uint32_t aktMillis = millis();
  if (aktMillis - lastMillis >= zeitIntervall) {  // 1 Sekunde?
    lastMillis = aktMillis;
    zeitscheiben++;
    runAll(zeitscheiben);
  }
}

die Klasse:

/* Boje mit 6 Zeiten
Ausgebe mit FastLED
*/
#include <FastLED.h>

enum Farbe {BLACK,RED,GREEN,BLUE, YELLOW, CYAN,PURPLE,WHITE};
const CRGB colors[] = {{0x00,0x00,0x00}, {0xFF,0x00,0x00}, {0x00,0xFF,0x00}, {0x00,0x00,0xFF}, 
                        {0xFF,0xFF,0x00}, {0x00,0xFF,0xFF}, {0xFF,0x00,0xFF}, {0xFF,0xFF,0xFF}
                       };
const byte anzColor = sizeof(colors)/sizeof(colors[0]);

class BojeFastLed {
  public:
     BojeFastLed(byte pixelNr, Farbe farbeAn, bool startZustand,  
          int8_t time0, int8_t time1, int8_t  time2 = -1, int8_t  time3 = -1, int8_t  time4 = -1, int8_t  time5 = -1, int8_t  time6 = -1): 
            pixelNr(pixelNr), farbeAn(farbeAn), startZustand(startZustand) {
            time[0] = time0;
            time[1] = time1;
            time[2] = time2;
            time[3] = time3;
            time[4] = time4;
            time[5] = time5;
    }    
    
    static void setCRGB(CRGB *stripe) {                                  // <-- Die Übergabemethode
      leds = stripe;
    }     
    
    void init() {
      if (startZustand) farbe = farbeAn;
      else farbe = 0;
      leds[pixelNr] = colors[farbe];
    }
    byte run(uint32_t zeit) {
      // if (!initStripe) return;
      if (zeit - lastZeit >= time[idx]) {
        lastZeit = zeit;
        idx++;
        if (farbe == 0) farbe = farbeAn;
        else farbe = 0;
        if (idx >= anzahlZeit || time[idx] <0) {
          if (startZustand) farbe = farbeAn;
          else farbe = 0;
          idx = 0;
        }
        leds[pixelNr] = colors[farbe];
        return 1;
      }
      return 0;
    }
  private:
    static const byte anzahlZeit = 6;
    static CRGB *leds;                                                             // <-- die Zielvariable
    const byte pixelNr;
    const byte startZustand;  
    Farbe farbeAn;    
    Farbe farbe;
    byte idx;
    uint32_t lastZeit;
    int8_t time[anzahlZeit];
};

Das sind die Fehlermeldungen:

C:\Users\Tommy\AppData\Local\Temp\ccVfHJit.ltrans0.ltrans.o: In function `BojeFastLed::setCRGB(CRGB*)':

C:\Users\Tommy\AppData\Local\Temp\arduino_build_307451\sketch/BojeFastLed.h:26: undefined reference to `BojeFastLed::leds'

C:\Users\Tommy\AppData\Local\Temp\arduino_build_307451\sketch/BojeFastLed.h:26: undefined reference to `BojeFastLed::leds'

C:\Users\Tommy\AppData\Local\Temp\ccVfHJit.ltrans0.ltrans.o: In function `init':

C:\Users\Tommy\AppData\Local\Temp\arduino_build_307451\sketch/BojeFastLed.h:32: undefined reference to `BojeFastLed::leds'

C:\Users\Tommy\AppData\Local\Temp\arduino_build_307451\sketch/BojeFastLed.h:32: undefined reference to `BojeFastLed::leds'

C:\Users\Tommy\AppData\Local\Temp\ccVfHJit.ltrans0.ltrans.o: In function `run':

C:\Users\Tommy\AppData\Local\Temp\arduino_build_307451\sketch/BojeFastLed.h:46: undefined reference to `BojeFastLed::leds'

C:\Users\Tommy\AppData\Local\Temp\ccVfHJit.ltrans0.ltrans.o:C:\Users\Tommy\AppData\Local\Temp\arduino_build_307451\sketch/BojeFastLed.h:46: more undefined references to `BojeFastLed::leds' follow

collect2.exe: error: ld returned 1 exit status

Kann mir mal jemand einen Stups in die richtige Richtung geben?

Gruß Tommy

Eine statische Klassenvariable musst Du auch definieren, die Deklaration in der Klasse reicht da nicht aus, da sie ja beim Instanziieren nicht mit angelegt wird ( sie gehört ja nicht zum Objekt ).

Am Ende von BojeFastLed.h musst Du also noch ein

CRGB *BojeFastLed::leds;

einfügen. Dann sollte der Linker zufrieden sein.

Ich will es ja nicht außerhalb der Klasse anlegen, dann kann ich extern verwenden.

In der Klasse habe ich ja schon

static CRGB *leds;

oder habe ich Dich falsch verstanden?

Gruß Tommy

Das ist aber nur die Deklaration.
Da Du bei der Definition den Klassennnamen mit angibst, kann es extern nicht verwendet werden.

Edit: das ist so ahnlich, als wenn Du die Methodendefinitionen ausserhalb des class { }; machst. Da gibst Du ja auch den Klassennamen an, damit der Compiler weis, wozu das gehört.
Da die Deklaration vorhanden ist, meckert auch nicht der Compiler, sondern erst der Linker.

Du hast Recht, er meckert nicht mehr und es funktioniert. Wieder was gelernt.
Danke Dir.

Gruß Tommy

Gerne

MicroBahner:
Eine statische Klassenvariable musst Du auch definieren, die Deklaration in der Klasse reicht da nicht aus, da sie ja beim Instanziieren nicht mit angelegt wird ( sie gehört ja nicht zum Objekt ).

Am Ende von BojeFastLed.h musst Du also noch ein

CRGB *BojeFastLed::leds;

einfügen. Dann sollte der Linker zufrieden sein.

Das gehört aber eigentlich in eine separate .cpp Datei, nicht ans Ende der .hpp,
ansonsten kann man die .h Datei nur in ein einziges Modul aus dem Projekt includen,
sonst verwandelt sich undefiniert in mehrfach definiert.

Das ist für den allgemeinen Fall auf jeden Fall richtig. Für die Definition einer allgemeinen Lib taugt das so nicht. Dann sind aber üblicherweise ( wenn auch nicht immer ) auch die Methodendefinitionen in einer eigenen .cpp, in die dann auch diese Definition hineingehört.

Der Hinweis ist jedenfalls richtig und wichtig, danke.