Undefined reference to '' while compiling own library

When I try to compile my code I keep getting this error

C:\Users\maxim\AppData\Local\Temp\cczhNVX5.ltrans0.ltrans.o: In function `TM1637Display::stop() [clone .constprop.33]':
<artificial>:(.text+0x30a): undefined reference to `hdtelevize'
<artificial>:(.text+0x30c): undefined reference to `hdtelevize'
C:\Users\maxim\AppData\Local\Temp\cczhNVX5.ltrans0.ltrans.o: In function `TM1637Display::writeByte(unsigned char) [clone .constprop.32]':
<artificial>:(.text+0x362): undefined reference to `hdtelevize'
<artificial>:(.text+0x37a): undefined reference to `hdtelevize'
<artificial>:(.text+0x38a): undefined reference to `hdtelevize'
C:\Users\maxim\AppData\Local\Temp\cczhNVX5.ltrans0.ltrans.o:<artificial>:(.text+0x3a4): more undefined references to `hdtelevize' follow
collect2.exe: error: ld returned 1 exit status
*** [.pio\build\uno\firmware.elf] Error 1

main.cpp

#include <Arduino.h> // Arduino
#include <Wire.h>    // Připojení
#include <ClockShield.h> // Displej
ShieldDisplay tmdisplej(7, 8);
ShieldClock rtchodiny;
void setup()
{
  Serial.begin(9600); // Spuštení sériové komunikace
  if (!rtchodiny.begin())
  { // Kontrola připojení hodin
    Serial.println("Clock not connected!");
    while (true)
      ;
  }
  if (!rtchodiny.isrunning())
  { // Kontrol spuštění hodin
    Serial.println("Clock not running. Starting now...");
  }
  tmdisplej.setBrightness(15);       // Podsvícení 8-15
  tmdisplej.temp();
}

void loop()
{
}

lib/ClockShield/ClockShield.h

#ifndef ClockShield_h

#define ClockShield_h

#include <Arduino.h>

#include <TM1637Display.h>

#include <RTClib.h>

extern TM1637Display hdtelevize;

extern RTC_DS1307 hodiny;

class ShieldDisplay

{

public:

    ShieldDisplay(uint8_t pinCLK, uint8_t pinDIO);

    void setBrightness(uint8_t brightness);

    void temp();
};

class ShieldClock

{

public:

    ShieldClock();

    boolean begin();

    uint8_t isrunning();

};

#endif

lib/ClockShield/ClockShield.cpp

#include <Arduino.h>

#include "ClockShield.h"

#include <TM1637Display.h>

#include <RTClib.h>

ShieldDisplay::ShieldDisplay(uint8_t pinCLK, uint8_t pinDIO)

{

    hdtelevize = TM1637Display(pinCLK, pinDIO);

}

void ShieldDisplay::setBrightness(uint8_t brightness)

{

    hdtelevize.setBrightness(brightness);

}

void ShieldDisplay::temp()

{

    DateTime ted = hodiny.now();

    vypis[0] = hdtelevize.encodeDigit(ted.hour() / 10);

    vypis[1] = hdtelevize.encodeDigit(ted.hour() % 10);

    vypis[2] = hdtelevize.encodeDigit(ted.minute() / 10);

    vypis[3] = hdtelevize.encodeDigit(ted.minute() % 10);

    if ((millis() % 1000) >= 500)

    {

        hdtelevize.setSegments(vypis);

    }

    else

    {

        vypis[1] = vypis[1] + 128;

        hdtelevize.setSegments(vypis);

    }

}


ShieldClock::ShieldClock()

{

    hodiny = RTC_DS1307();

}

boolean ShieldClock::begin()

{

    return hodiny.begin();

}

uint8_t ShieldClock::isrunning()

{

    return hodiny.isrunning();

}

lib/TM1637Display/TM1637Display.cpp (not whole)

void TM1637Display::stop()

{

  pinMode(m_pinDIO, OUTPUT);

  bitDelay();

  pinMode(m_pinClk, INPUT);

  bitDelay();

  pinMode(m_pinDIO, INPUT);

  bitDelay();

}

  

bool TM1637Display::writeByte(uint8_t b)

{

  uint8_t data = b;

  // 8 Data Bits

  for(uint8_t i = 0; i < 8; i++) {

    // CLK low

    pinMode(m_pinClk, OUTPUT);

    bitDelay();

    

  // Set data bit

    if (data & 0x01)

      pinMode(m_pinDIO, INPUT);

    else

      pinMode(m_pinDIO, OUTPUT);

    

    bitDelay();

  

  // CLK high

    pinMode(m_pinClk, INPUT);

    bitDelay();

    data = data >> 1;

  }

  

  // Wait for acknowledge

  // CLK to zero

  pinMode(m_pinClk, OUTPUT);

  pinMode(m_pinDIO, INPUT);

  bitDelay();

  

  // CLK to high

  pinMode(m_pinClk, INPUT);

  bitDelay();

  uint8_t ack = digitalRead(m_pinDIO);

  if (ack == 0)

    pinMode(m_pinDIO, OUTPUT);

    

  bitDelay();

  pinMode(m_pinClk, OUTPUT);

  bitDelay();

  

  return ack;

}

I know it is kinda long, but I searched for this issue and I could not find any working solution. Thanks for help!

My library is ClockShield, TM1637Display is not mine.

You’re only declaring this variable as extern, as in “this variable is not created here, but somewhere else, and referenced by this code” but I don’t see any global variable definition for that varaible.

Where is the variable created (defined) with a

TM1637Display hdtelevize;

global definition?

do you mean this?

hdtelevize = TM1637Display(pinCLK, pinDIO);

it is in ClockShield.cpp

But this code attempts to assign a value to a variable that hasn’t been created yet.

Can you try adding

TM1637Display hdtelevize;

under

#include <RTClib.h>

in ClockShield.cpp?

TM1637Display hdtelevize;

wont work but if I use

TM1637Display hdtelevize(7, 8);

then it works, but I want that 7, 8 to be chosable by user

Then you can construct the display object in the same go as the construction of the ShieldDisplay object (list initializer).

Remove that line and add in the ShieldDisplay header class

private:
	TM1637Display hdtelevize; 

and rewrite the constructor

ShieldDisplay::ShieldDisplay(uint8_t pinCLK, uint8_t pinDIO)
     : hdtelevize(pinCLK, pinDIO)
{
}

But this will also make the TM1637Display display object private to the class. You may change it to public if you want.

You can also use a pointer to the object, initialize it with nullptr and then new it in the constructor.

  • it works but class ShieldDisplay cannot acces hodiny and vice versa

Same thing. Either globally instantiate the object or make it a member of the ShieldDisplay class and instantitate it with it in the constructor.

how would that look? i don’t really understand this

For global instanciation: Add the line

RTC_DS1307 hodiny = RTC_DS1307();

below

in ClockShield.cpp.

Thanks a lot :smile: