0

I am getting this error:

Linking CXX executable muse3.exe
driver/libmuse_driver.a(qttimer.obj):qttimer.cpp:(.rdata$.refptr._ZTVN8MusECore10InnerTimerE[.refptr._ZTVN8MusECore10InnerTimerE]+0x0): undefined reference to `vtable for MusECore::InnerTimer'
collect2.exe: error: ld returned 1 exit status
mingw32-make[2]: *** [muse\CMakeFiles\muse.dir\build.make:212: muse/muse3.exe] Error 1
mingw32-make[1]: *** [CMakeFiles/Makefile2:600: muse/CMakeFiles/muse.dir/all] Error 2
mingw32-make: *** [Makefile:151: all] Error 2

I understand that the message is a little unclear and the issue is probably with some method.

Here is my .h file:

#ifndef __QTTIMER_H__
#define __QTTIMER_H__


#include <fcntl.h>
#include <QThread>
#include <QBasicTimer>
#include <QTimerEvent>

#include "timerdev.h"

namespace MusECore {

//---------------------------------------------------------
//   QtTimer
//---------------------------------------------------------

class InnerTimer : public QObject {
  Q_OBJECT
  int writePipe;
  long int tickCount;
  QBasicTimer timer;
public:
   void setupTimer(int fd, int timeoutms);
   ~InnerTimer();
   long int getTick();
   bool isRunning() { return timer.isActive(); }

protected:
   void timerEvent(QTimerEvent *event);

};

class QtTimer : public Timer, public QThread {

    int writePipe;
    int readPipe;
    bool keepRunning;
    InnerTimer *innerTimer;
    int timeoutms;
    public:
       QtTimer();
       virtual ~QtTimer();

       virtual signed int initTimer(unsigned long init);
       virtual long unsigned int setTimerResolution(unsigned long resolution);
       virtual long unsigned int getTimerResolution();
       virtual long unsigned int setTimerFreq(unsigned long freq);
       virtual long unsigned int getTimerFreq();

       virtual bool startTimer();
       virtual bool stopTimer();
       virtual long unsigned int getTimerTicks(bool printTicks=false);

       void setFindBestTimer(bool ) { }
    private:
       virtual void run();
};

} // namespace MusECore

#endif //__QTTIMER_H__

And here is the .cpp file:

#include <cstdio>
#include <unistd.h>
#include <fcntl.h>
#include "qttimer.h"

#ifndef TIMER_DEBUG
#define TIMER_DEBUG 1
#endif

#ifdef _WIN32
#define pipe(fds) _pipe(fds, 4096, _O_BINARY)
#endif

namespace MusECore {


  QtTimer::QtTimer()
     {
     if(TIMER_DEBUG)
       fprintf(stderr,"QtTimer::QtTimer(this=%p) called\n",this);
     innerTimer = NULL;
     timeoutms = 10;
     readPipe=-1;
     writePipe=-1;
     }

  QtTimer::~QtTimer()
    {
    if(TIMER_DEBUG)
       fprintf(stderr,"QtTimer::~QtTimer(this=%p) called\n",this);
    exit(); // thread exit
    }

  signed int QtTimer::initTimer(unsigned long)
  {
    if(TIMER_DEBUG)
      printf("QtTimer::initTimer(this=%p)\n",this);

    int filedes[2];         // 0 - reading   1 - writing
    if (pipe(filedes) == -1) {
          perror("QtTimer - creating pipe failed");
          exit(-1);
          }
#ifndef _WIN32
    int rv = fcntl(filedes[1], F_SETFL, O_NONBLOCK);
    if (rv == -1)
          perror("set pipe O_NONBLOCK");
#endif
    if (pipe(filedes) == -1) {
          perror("QtTimer - creating pipe1");
          exit(-1);
          }
    writePipe = filedes[1];
    readPipe = filedes[0];

    return filedes[0];
  }

  long unsigned int QtTimer::setTimerResolution(unsigned long)
    {
    return 0;
    }

  long unsigned int QtTimer::setTimerFreq(unsigned long freq)
    {
    if (freq > 1000)
      freq = 1000;
    if (freq < 100)
      freq = 100;
    timeoutms = 1000/freq;
    return 1000/timeoutms;
    }

  long unsigned int QtTimer::getTimerResolution()
    {
    return  20;
    }

  long unsigned int QtTimer::getTimerFreq()
    {
    return 1000/timeoutms;
    }

  bool QtTimer::startTimer()
    {
    QThread::start();
    return true;
    }

  bool QtTimer::stopTimer()
    {
    QThread::quit();
    return true;
    }

  unsigned long int  QtTimer::getTimerTicks(bool /*printTicks*/)
    {

    if(TIMER_DEBUG)
      printf("getTimerTicks()\n");
    unsigned long int nn;
    if (readPipe==-1) {
        fprintf(stderr,"QtTimer::getTimerTicks(): no pipe open to read!\n");
        return 0;
    }
    if (read(readPipe, &nn, sizeof(char)) != sizeof(char)) {
        fprintf(stderr,"QtTimer::getTimerTicks(): error reading pipe\n");
        return 0;
        }
    //return nn;

    return innerTimer != 0 ? innerTimer->getTick() : 0;

    }

  void QtTimer::run()
  {

    //bool keepRunning = true;
    innerTimer = new InnerTimer();
    innerTimer->setupTimer(writePipe, timeoutms); // make sure it is running in the right thread

    exec();
  }

  void InnerTimer::setupTimer(int fd, int timeoutms)
  {
    tickCount=0;
    writePipe = fd;
    timer.start(timeoutms, this);
    printf("InnerTimer::setupTimer() started\n");

  }

  InnerTimer::~InnerTimer()
  {
    timer.stop();
  }

  void InnerTimer::timerEvent(QTimerEvent *event)
  {
    //if (tickCount%1000)
      //printf("InnerTimer::timerEvent %ld ++++++++++++++++++++++\n",tickCount);

    if (event->timerId() == timer.timerId()) {
      tickCount++;
      write(writePipe,"t",1);
    }

  }

  long int InnerTimer::getTick()
  {
    return tickCount;
  }

} // namespace MusECore

I have read other posts on this error, and they mostly point to some virtual methods that were not defined. But, to me, it seems that everything is defined properly and I also have the destructor defined.

Can anybody point me out to what is wrong?

Benjamin Bihler
  • 1,612
  • 11
  • 32
  • 1
    In my experience you can get similar errors if your project isn't properly up to date. E.g. you've modifed a header file but not recompiled all the source files that depend upon it. Ask yourself what the last change you made was before seeing this error. – john Jan 22 '19 at 08:57
  • Thanks, but I recompiled from scratch. It hangs always at that point. I am trying to port the application from Linux to mingw on win64, so there is no previous successful compilation. – Aquila Rubra Jan 22 '19 at 09:13
  • 1
    Since InnerTimer is a child of QObject, it might also be necessary to run qmake again. Have you also tried that? – Benjamin Bihler Jan 22 '19 at 09:17
  • I just use this command: "mingw32-make -j1 all". Not using qmake at all. When it compiles on Linux, there is an initial cmake to configure, then a plain make, as I am using. – Aquila Rubra Jan 22 '19 at 09:47
  • I have not been using qt with cmake yet, but I am quite sure that cmake will perform the same steps as qmake would. Your make command is fine, the problem is somewhere else. Have you rerun cmake on Windows? – Benjamin Bihler Jan 22 '19 at 09:53
  • Yes, I have rebuilt the whole thing from scratch, with cmake command also. – Aquila Rubra Jan 22 '19 at 10:00
  • Then I guess that you have to provide a minimal example that shows the problem. I cannot compile your code, because for example timerdev.h is missing here. Is it a file you have created? Please reduce your code as much as possible. – Benjamin Bihler Jan 22 '19 at 10:04
  • By the way, here seems to be a documentation about how to combine qt and cmake: https://stackoverflow.com/questions/47471629/fail-to-use-q-object-macro-in-cmake-project – Benjamin Bihler Jan 22 '19 at 10:11
  • I am not that proficient in C++ to make the example, but I am asking its author (who could duplicate my same issue, by the way) if he can do that. I will post any update, thanks. – Aquila Rubra Jan 22 '19 at 10:43

0 Answers0