Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Installation and Deployment
  4. Weird undefined error regarding object in a class when it has been defined...
Forum Updated to NodeBB v4.3 + New Features

Weird undefined error regarding object in a class when it has been defined...

Scheduled Pinned Locked Moved Solved Installation and Deployment
7 Posts 2 Posters 351 Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • D Offline
    D Offline
    DexTr
    wrote on last edited by DexTr
    #1

    So, I've read a lot about undefined errors, but I'm confused about my situation, and even a little worried since the error message isn't something "clean".

    Here's my code. First, the .h file :

    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    
    #include <QMainWindow>
    #include <QtSerialPort/QSerialPort>
    #include <QSerialPortInfo>
    #include <QProgressDialog>
    #include <QProgressBar>
    #include <QThread>
    #include <QFile>
    #include <QFileDialog>
    #include <QLabel>
    #include <QString>
    #include <QIODevice>
    extern "C"{
    #include "bootloader.h"
    }
    
    
    
    QT_BEGIN_NAMESPACE
    namespace Ui { class MainWindow; }
    QT_END_NAMESPACE
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        MainWindow(QWidget *parent = nullptr);
        ~MainWindow();
    
    private:
        Ui::MainWindow *ui;
    };
    
    class BootLoader
    {
        public:
            BootLoader();
    
            ~BootLoader();
            BOOTLOADERERROR err;
            BOOTLOADER b;
            UnionX addr;
            QString port;
            QSerialPortInfo portinfo;
    
            static QSerialPort BootSerial;
    };
    #endif // MAINWINDOW_H
    

    Now for the .cpp :

    void boot_rst(unsigned char value)
    {
        BootLoader::BootSerial.setRequestToSend(value);
    }
    
    unsigned char write_uart(unsigned char data_byte_count, unsigned char* data_to_write)
    {
        return BootLoader::BootSerial.write((char*) data_to_write, data_byte_count);
    }
    
    unsigned char read_uart(unsigned char data_byte_count, unsigned char* data_read)
    {
        return BootLoader::BootSerial.read((char*) data_read, data_byte_count);
    }
    
    void wait(unsigned int micros)
    {
        QObject().thread()->usleep(micros);
    }
    
    BootLoader::BootLoader()
    {
        err = INIT_NOT_DONE;
        b.init_done = 0;
        b.boot_ready = 0;
        addr.address_l = 0;
        port = QString("COM3");
        portinfo = QSerialPortInfo(port);
        //BootSerial = new QSerialPort(nullptr);
    
        BootLoader::BootSerial.QSerialPort::setPort(portinfo);
        BootLoader::BootSerial.setBaudRate(115200);
        BootLoader::BootSerial.setParity(QSerialPort::EvenParity);
    
        bootloaderInitQt(&b, boot_rst, write_uart, read_uart, wait);
    }
    

    I omitted some stuff which isn't relevant to the part I'm looking at. Now for the error :

    :-1: erreur : debug/mainwindow.o:mainwindow.cpp:(.rdata$.refptr._ZN10BootLoader10BootSerialE[.refptr._ZN10BootLoader10BootSerialE]+0x0): undefined reference to `BootLoader::BootSerial'
    

    Could someone help point out what I'm doing wrong here ? The objective is to have those functions write_uart, read_uart etc serve as pointers to functions from the QSerialPort module. I have made a previous version of the bootloader (which works, and is in a .c file), so I'm fairly confident it isn't the cause of the problem. Any idea would be helpful.

    Edit to add : I'm using the .c bootloader for compilation, which is where the BOOTLOADER and BOOTLOADERERROR types are defined (one is a structure, the other is an enum to point out what the error is during the program.)

    Worth noting, I don't have a lot of experience in C++ ^^"

    1 Reply Last reply
    0
    • D Offline
      D Offline
      DexTr
      wrote on last edited by
      #5

      Finally figured it out ! I was on the right track, but I wasn't doing things "smart". I ended up making an instance of my BootLoader class in my MainWindow, so I could access the members. I had to put the BootLoader members on public, I had no choice here. But the instanciation made calling on the variables so much easier.

      In short, I had only done half the work when I wrote my class, I had to actually use it somewhere.

      Thanks for the answers ! And I'll be brushing up my C++ for future use.

      Here's what the new code looks like, for reference :

      #ifndef MAINWINDOW_H
      #define MAINWINDOW_H
      
      #include <QMainWindow>
      #include <QtSerialPort/QSerialPort>
      #include <QSerialPortInfo>
      #include <QProgressDialog>
      #include <QProgressBar>
      #include <QThread>
      #include <QFile>
      #include <QFileDialog>
      #include <QLabel>
      #include <QString>
      #include <QIODevice>
      extern "C"{
      #include "bootloader.h"
      }
      
      
      
      QT_BEGIN_NAMESPACE
      namespace Ui { class MainWindow; }
      QT_END_NAMESPACE
      
      class BootLoader
      {
          public:
              BootLoader();
      
              ~BootLoader();
          //private:
              BOOTLOADERERROR err;
              BOOTLOADER b;
              UnionX addr;
              QString port;
              QSerialPortInfo portinfo;
      
              QSerialPort BootSerial;
      };
      
      class MainWindow : public QMainWindow
      {
          Q_OBJECT
      
      public:
          MainWindow(QWidget *parent = nullptr);
          ~MainWindow();
      
      private:
          Ui::MainWindow *ui;
      
      
          QLabel *statusLabel;
          QLabel *sizeLabel;
          QProgressBar *statusProgressBar;
          QLabel *LabelGive;
          QLabel *LabelGet;
          QSerialPort *serial;
          QString port;
          QSerialPortInfo portinfo;
      
          BootLoader B;
          void boot_rst(unsigned char value);
          unsigned char write_uart(unsigned char data_byte_count, unsigned char* data_to_write);
          unsigned char read_uart(unsigned char data_byte_count, unsigned char* data_read);
          void wait(unsigned int micros);
      };
      
      
      #endif // MAINWINDOW_H
      

      And the .cpp :

      void MainWindow::boot_rst(unsigned char value)
      {
          B.BootSerial.setRequestToSend(value);
      }
      
      unsigned char MainWindow::write_uart(unsigned char data_byte_count, unsigned char* data_to_write)
      {
          return B.BootSerial.write((char*) data_to_write, data_byte_count);
      }
      
      unsigned char MainWindow::read_uart(unsigned char data_byte_count, unsigned char* data_read)
      {
          return B.BootSerial.read((char*) data_read, data_byte_count);
      }
      
      void MainWindow::wait(unsigned int micros)
      {
          QObject().thread()->usleep(micros);
      }
      
      BootLoader::BootLoader()
      {
          err = INIT_NOT_DONE;
          b.init_done = 0;
          b.boot_ready = 0;
          addr.address_l = 0x08000000;
          port = QString("COM3");
          portinfo = QSerialPortInfo(port);
          //BootSerial = new QSerialPort(nullptr);
      
          /*BootLoader::BootSerial.setPort(portinfo);
          BootLoader::BootSerial.setBaudRate(115200);
          BootLoader::BootSerial.setParity(QSerialPort::EvenParity);
          BootLoader::BootSerial.open(QIODeviceBase::ReadWrite);
      
          bootloaderInitQt(&b, boot_rst, write_uart, read_uart, wait);*/
          this-> BootSerial.setPort(portinfo);
          BootSerial.setBaudRate(115200);
          BootSerial.setParity(QSerialPort::EvenParity);
      }
      
      unsigned char value = 0;
      
      MainWindow::~MainWindow()
      {
          delete ui;
      }
      
      BootLoader::~BootLoader()
      {
      
      }
      
      1 Reply Last reply
      0
      • J.HilkJ Offline
        J.HilkJ Offline
        J.Hilk
        Moderators
        wrote on last edited by
        #2

        hi, and welcome

        first off, please use code tags for your code, those make reading them much easier :D its ``` in the beginning and the end of the code block

        secondly:
        static QSerialPort BootSerial;

        don't make stack allocated QObjects static! its not permitted and my lead to problems

        3rdly:
        BootLoader::BootSerial.QSerialPort::setPort(portinfo); this os most definitely the wrong way to access the set port function of your serialport instance :D

        class BootLoader
        {
        public:
            BootLoader();
        
            ~BootLoader();
        private:
            BOOTLOADERERROR err;
            BOOTLOADER b;
            UnionX addr;
            QString port;
            QSerialPortInfo portinfo;
        
           QSerialPort BootSerial;
        };
        
        BootLoader::BootLoader()
        {
        err = INIT_NOT_DONE;
        b.init_done = 0;
        b.boot_ready = 0;
        addr.address_l = 0;
        port = QString("COM3");
        portinfo = QSerialPortInfo(port);
        
        //old and wrong
        //BootLoader::BootSerial.QSerialPort::setPort(portinfo);
        //BootLoader::BootSerial.setBaudRate(115200);
        //BootLoader::BootSerial.setParity(QSerialPort::EvenParity);
        
        this-> BootSerial.setPort(portinfo); // this can (in this case) be omitted in c++, the so following is also ok:
        BootSerial.setBaudRate(115200);
        BootSerial.setParty(QSerialPort::EvenParity);
        
        }
        

        Worth noting, I don't have a lot of experience in C++ ^^"

        I could tell :P


        Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


        Q: What's that?
        A: It's blue light.
        Q: What does it do?
        A: It turns blue.

        1 Reply Last reply
        1
        • D Offline
          D Offline
          DexTr
          wrote on last edited by DexTr
          #3

          Thanks for the code block tip, makes a world of difference !

          The reason I put the parameters as public in the BootLoader class is because I have an issue when setting the pointers to the functions I want. So now, this :

          void boot_rst(unsigned char value)
          {
              BootLoader::BootSerial.setRequestToSend(value);
          }
          

          returns the error : "BootSerial is a private member of BootLoader", hence why I thought putting them as public would help.

          J.HilkJ 1 Reply Last reply
          0
          • D Offline
            D Offline
            DexTr
            wrote on last edited by
            #4

            Tried a few more things before I realized I didn't remove the static before my BootSerial member. Now I just have "two" errors to solve, the fact that BootSerial is private or protected and can't be accessed, and the fact that it's a non-static member and I'm using it wrong. It's also something that is going to affect the UnionX member (which is a union between a long int and an array of four bytes for storing an address and rearranging the byte order), so now it's just a matter of what am I doing wrong here.

            1 Reply Last reply
            0
            • D Offline
              D Offline
              DexTr
              wrote on last edited by
              #5

              Finally figured it out ! I was on the right track, but I wasn't doing things "smart". I ended up making an instance of my BootLoader class in my MainWindow, so I could access the members. I had to put the BootLoader members on public, I had no choice here. But the instanciation made calling on the variables so much easier.

              In short, I had only done half the work when I wrote my class, I had to actually use it somewhere.

              Thanks for the answers ! And I'll be brushing up my C++ for future use.

              Here's what the new code looks like, for reference :

              #ifndef MAINWINDOW_H
              #define MAINWINDOW_H
              
              #include <QMainWindow>
              #include <QtSerialPort/QSerialPort>
              #include <QSerialPortInfo>
              #include <QProgressDialog>
              #include <QProgressBar>
              #include <QThread>
              #include <QFile>
              #include <QFileDialog>
              #include <QLabel>
              #include <QString>
              #include <QIODevice>
              extern "C"{
              #include "bootloader.h"
              }
              
              
              
              QT_BEGIN_NAMESPACE
              namespace Ui { class MainWindow; }
              QT_END_NAMESPACE
              
              class BootLoader
              {
                  public:
                      BootLoader();
              
                      ~BootLoader();
                  //private:
                      BOOTLOADERERROR err;
                      BOOTLOADER b;
                      UnionX addr;
                      QString port;
                      QSerialPortInfo portinfo;
              
                      QSerialPort BootSerial;
              };
              
              class MainWindow : public QMainWindow
              {
                  Q_OBJECT
              
              public:
                  MainWindow(QWidget *parent = nullptr);
                  ~MainWindow();
              
              private:
                  Ui::MainWindow *ui;
              
              
                  QLabel *statusLabel;
                  QLabel *sizeLabel;
                  QProgressBar *statusProgressBar;
                  QLabel *LabelGive;
                  QLabel *LabelGet;
                  QSerialPort *serial;
                  QString port;
                  QSerialPortInfo portinfo;
              
                  BootLoader B;
                  void boot_rst(unsigned char value);
                  unsigned char write_uart(unsigned char data_byte_count, unsigned char* data_to_write);
                  unsigned char read_uart(unsigned char data_byte_count, unsigned char* data_read);
                  void wait(unsigned int micros);
              };
              
              
              #endif // MAINWINDOW_H
              

              And the .cpp :

              void MainWindow::boot_rst(unsigned char value)
              {
                  B.BootSerial.setRequestToSend(value);
              }
              
              unsigned char MainWindow::write_uart(unsigned char data_byte_count, unsigned char* data_to_write)
              {
                  return B.BootSerial.write((char*) data_to_write, data_byte_count);
              }
              
              unsigned char MainWindow::read_uart(unsigned char data_byte_count, unsigned char* data_read)
              {
                  return B.BootSerial.read((char*) data_read, data_byte_count);
              }
              
              void MainWindow::wait(unsigned int micros)
              {
                  QObject().thread()->usleep(micros);
              }
              
              BootLoader::BootLoader()
              {
                  err = INIT_NOT_DONE;
                  b.init_done = 0;
                  b.boot_ready = 0;
                  addr.address_l = 0x08000000;
                  port = QString("COM3");
                  portinfo = QSerialPortInfo(port);
                  //BootSerial = new QSerialPort(nullptr);
              
                  /*BootLoader::BootSerial.setPort(portinfo);
                  BootLoader::BootSerial.setBaudRate(115200);
                  BootLoader::BootSerial.setParity(QSerialPort::EvenParity);
                  BootLoader::BootSerial.open(QIODeviceBase::ReadWrite);
              
                  bootloaderInitQt(&b, boot_rst, write_uart, read_uart, wait);*/
                  this-> BootSerial.setPort(portinfo);
                  BootSerial.setBaudRate(115200);
                  BootSerial.setParity(QSerialPort::EvenParity);
              }
              
              unsigned char value = 0;
              
              MainWindow::~MainWindow()
              {
                  delete ui;
              }
              
              BootLoader::~BootLoader()
              {
              
              }
              
              1 Reply Last reply
              0
              • D DexTr

                Thanks for the code block tip, makes a world of difference !

                The reason I put the parameters as public in the BootLoader class is because I have an issue when setting the pointers to the functions I want. So now, this :

                void boot_rst(unsigned char value)
                {
                    BootLoader::BootSerial.setRequestToSend(value);
                }
                

                returns the error : "BootSerial is a private member of BootLoader", hence why I thought putting them as public would help.

                J.HilkJ Offline
                J.HilkJ Offline
                J.Hilk
                Moderators
                wrote on last edited by
                #6

                @DexTr somehow you stopped reading after the class definition I gave. The most relevant part was just a little bit further down:

                this-> BootSerial.setPort(portinfo); // this can (in this case) be omitted in c++, the so following is also ok:
                BootSerial.setBaudRate(115200);
                BootSerial.setParty(QSerialPort::EvenParity);
                

                but, you got it working, and thats what matters!


                Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


                Q: What's that?
                A: It's blue light.
                Q: What does it do?
                A: It turns blue.

                D 1 Reply Last reply
                0
                • J.HilkJ J.Hilk

                  @DexTr somehow you stopped reading after the class definition I gave. The most relevant part was just a little bit further down:

                  this-> BootSerial.setPort(portinfo); // this can (in this case) be omitted in c++, the so following is also ok:
                  BootSerial.setBaudRate(115200);
                  BootSerial.setParty(QSerialPort::EvenParity);
                  

                  but, you got it working, and thats what matters!

                  D Offline
                  D Offline
                  DexTr
                  wrote on last edited by
                  #7

                  @J-Hilk I did read that part and implemented it, but the issues were still there. It was more of a "I was using the class like my left foot" problem.

                  I got new errors but none warranting a continuation of that thread. Still, thank you for your time and patience !

                  1 Reply Last reply
                  1

                  • Login

                  • Login or register to search.
                  • First post
                    Last post
                  0
                  • Categories
                  • Recent
                  • Tags
                  • Popular
                  • Users
                  • Groups
                  • Search
                  • Get Qt Extensions
                  • Unsolved