Why is the Q_OBJECT macro causing issues (Qt)? - c++

I am running QtCreator in OSX Lion, and anytime I create a class that requires the Q_OBJECT macro, I get an error when I try to build my application. The code for that class is below, as is the error I am recieving. Any clue what may be going on?
Note: I have already tried cleaning, running qmake and re-building to no avail.
#ifndef TASKLIST_H
#define TASKLIST_H
#include <QObject>
class TaskList : public QObject
{
Q_OBJECT
public:
explicit TaskList(QObject *parent = 0 );
public slots:
void addTask();
void displayTasks();
};
#endif // TASKLIST_H
And the error:
:-1: error: symbol(s) not found for architecture x86_64
:-1: error: collect2: ld returned 1 exit status

There still seems to be a bug in Qt Creator.
I have a large project with a number of classes all having Q_OBJECT and another number of classes not having Q_OBJECT. It works fine. However, if I add Q_OBJECT to one of the classes which didn't have it, I get this "collect2: ld returned 1 exit status" error when trying to build it.
Checking the build directory, I see that the moc file for this class is missing. Qt just does not create the moc files for it! However, if I remove the header and cpp files from the project and add them again, it works, the moc files are generated and the project is built successfully.
This problem seems to happen only if I have a class which did not have Q_OBJECT and it was built succesfully in the past. A fresh class with Q_OBJECT that was never compiled before adding "Q_OBJECT" always works fine.
So, if this problem happens and you are sure you included everything correctly (and commenting out Q_OBJECT lets the project to be built correctly), do the following:
remove the .h and .cpp files (where you just added the Q_OBJECT) from the project.
add them to the project again
clean project
build it again.
EDIT
In some cases running qmake (Build/Run qmake) followed by a Clean All is enough.

tasklist.h file
#ifndef TASKLIST_H
#define TASKLIST_H
#include <QObject>
class TaskList : public QObject
{
Q_OBJECT
public:
explicit TaskList(QObject *parent = 0 );
public slots:
void addTask(){};
void displayTasks(){};
};
#endif // TASKLIST_H
tasklist.cpp
#include "tasklist.h"
TaskList::TaskList(QObject *parent) :
QObject(parent)
{
}
main.cpp
#include <QtCore/QCoreApplication>
#include "tasklist.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
TaskList t;
return a.exec();
}
works fine, but it should be in separate files

Related

Q_OBJECT macro issue during build

I'm working on a project using QT. To link it with premake, I cloned the addon which generate a QT solution premake-qt. It works fine when it comes to use qt in general.
But I need to create custom signals so to do that, I had to add Q_OBJECT in my header file.
Here is the file:
#pragma once
#ifndef _WINDOW_H_
#define _WINDOW_H_
#include <QApplication>
#include <QWidget>
#include <QPushButton>
#include <QProgressBar>
#include <QSlider>
#include <QFileDialog>
#include <QtDebug>
#include <QFile>
#include <QTextStream>
#include <QMenu>
class WindowUI : public QWidget
{
Q_OBJECT
enum class State {
Save = 0,
Export = 1,
};
... // rest of header
So without the Q_OBJECT everything works fine, but when I build with it, I have an error.
>Moc'ing Window.h
>the specified path cannot be found.
And something I found is that it generates a moc_Window.args and a moc_Window.cpp in the vscode tree but the .cpp is not in my work directory.
If needed I can provide my premake.lua config file where I link QT if something is missing.
Do I have to run qmake on my project when I add Q_OBJECT ?
Try removing the class from VS project and adding it back. I've had similar issues when changing a normal class to QObject based (including Q_OBJECT macro). I think the issue is related to how the Qt VS add-in does the moc'cing.

Qt Quick + CMake + custom QObject results in undefined reference to `vtable'

I use Qt Quick to make small application to work with files.
Everything was working until one moment i executed in my build/ folder
rm -rf *
cmake ..
make
And then make halted with this error (lising is huge, i suppresed non-important part):
[100%] Linking CXX executable uint32_sort_gui
In function `LibController::~LibController()':
lib_controller.cpp:(.text+0x10): undefined reference to `vtable for LibController'
main.cpp.o: In function `int qmlRegisterType<LibController>(char const*, int, int, char const*)':
...
Here is my .hpp and .cpp files of the class:
lib_controller.hpp
#include <QObject>
#include <QString>
class LibController : public QObject{
Q_OBJECT
Q_PROPERTY(decltype(getProgress) progress READ getProgress NOTIFY ProgressChanged)
public:
explicit LibController(QObject *parent = 0);
~LibController();
double getProgress();
Q_INVOKABLE
void addFile(QString from_name, QString to_name);
Q_INVOKABLE
void sortFile();
signals:
void ProgressChanged();
private:
double current_progress;
FileManager* file_manager;
};
lib_controller.cpp
#include "lib_controller.hpp"
LibController::~LibController(){
delete file_manager;
}
double LibController::getProgress(){...}
void LibController::addFile(QString from_name, QString to_name){...}
void LibController::sortFile(){...}
main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlComponent>
#include "lib_controller.hpp"
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
// Registration of custom type
qmlRegisterType<LibController>("com.sort.controller", 0, 1, "LibController");
...
return app.exec();
}
And my CMakeLists.txt configuration.
I read another questions about this problem, but cleaning and rebuilding did not help (i even accidentally deleted whole project folder).
The problem persists, and i do not understand, how to fix it ...
UPD:
Here is full error message
UPD2:
After excluded LibController from the project and recompiling it, error is gone, but no window is showed to me. I can see from terminal that it is running, but no GUI popped up.
I guess problem is not in LibController, but somewhere else.
You need to add headers to the list of your source files for cmake to be able to run AUTOMOC on them.
This question has been already asked and answered here Changing location of header file causes missing vtable error when compiling with CMake
Since you call out the constructor in your header try adding this to the cpp file:
LibController::LibController(QObject *parent) : QObject(parent) {
}
Also, I have found that Rebuild All doesn't re-run qmake all the time. If you still see the issue run Build, Run qmake to make sure the header is getting processed.
According to comments in this question, you should
Rename your custom object header file to moc_*your header name*.hpp
Add path to this header to add_executable() function
Clear build/ directory and rerun CMake
Be somewhat happy in the end of the day
Hope this will help somebody, who tried to find last resort, like me.

Error in template generated by Qt in Visual Studio

So I've been trying to play around with Qt in Visual Studio. However, when I create a GUI application, the automatically generated template already contains a compiler error, namely:
Error (active) E1696 cannot open source file "ui_QtGuiApplication1.h" QtGuiApplication1 E:\visual_studio_projects\gui_test\QtGuiApplication1\QtGuiApplication1.h 4
I couldn't locate the ui_QtGuiApplication1.h header anywhere in the solution.
Removing the include statement results in the Ui class not being found. As far as I can tell, the Ui class is supposed to be located in ui_QtGuiApplication1.h.
QtGuiApplication1.h:
#include <QtWidgets/QMainWindow>
#include "ui_QtGuiApplication1.h"
class QtGuiApplication1 : public QMainWindow
{
Q_OBJECT
public:
QtGuiApplication1(QWidget *parent = Q_NULLPTR);
private:
Ui::QtGuiApplication1Class ui;
};
QtGuiApplication1.cpp:
QtGuiApplication1::QtGuiApplication1(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
}
Any help is appreciated.
EDIT: The ui_QtGuiApplication1.h was generated automatically by uic after the corresponding .ui file is saved in Qt Designer.
The file #include "ui_QtGuiApplication1.h is generated from your "QtGuiApplication1.ui" Designer file. Seems, that you didn't call the User Interface Compiler Tool (uic).

Changing location of header file causes missing vtable error when compiling with CMake

I need to transition from qmake to CMake for a large C++ project, but while working through a toy example I encountered some behavior that I don't understand. The example code features a single header file, and when that header file is moved into a subdirectory, I get a missing vtable error for the MainWindow class.
CMakeLists.txt
cmake_minimum_required(VERSION 2.6)
project(HelloCMake)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)
find_package(Qt5Widgets CONFIG REQUIRED)
include_directories("include")
set(INCLUDES include/mainwindow.h)
set(SOURCES
main.cpp
mainwindow.cpp
mainwindow.ui
)
add_executable(hello-cmake ${SOURCES}) # error
# add_executable(hello-cmake ${SOURCES} ${INCLUDES}) # no error
target_link_libraries(hello-cmake Qt5::Widgets)
include/mainwindow.h (boilerplate)
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow {
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow.cpp (boilerplate)
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow() {
delete ui;
}
main.cpp (boilerplate)
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
Here's what I see when I run make (after first running cmake .):
[ 20%] Automatic MOC and UIC for target hello-cmake
[ 20%] Built target hello-cmake_autogen
[ 40%] Linking CXX executable hello-cmake
Undefined symbols for architecture x86_64:
"vtable for MainWindow", referenced from:
MainWindow::MainWindow(QWidget*) in mainwindow.cpp.o
MainWindow::~MainWindow() in mainwindow.cpp.o
NOTE: a missing vtable usually means the first non-inline virtual member function has no definition.
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[2]: *** [hello-cmake] Error 1
make[1]: *** [CMakeFiles/hello-cmake.dir/all] Error 2
make: *** [all] Error 2
If I add the header to the target by swapping the second add_executable command for the first one in CMakeLists.txt, the error goes away. I can also make the error go away by moving the header into the base directory with the .cpp files. However, I'd like to know what's actually going on here. I understand the general value of including the header files in the target, but why is a missing vtable error generated when I don't do this? Unless I grossly misunderstand, all the contents of mainwindow.h should be available while mainwindow.cpp is being compiled by virtue of the #include, whether or not the header is part of the add_executable statement.
--
EDIT
Here are the contents of ui_mainwindow.h, in case they're somehow relevant.
/********************************************************************************
** Form generated from reading UI file 'mainwindow.ui'
**
** Created by: Qt User Interface Compiler version 5.10.1
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
#ifndef UI_MAINWINDOW_H
#define UI_MAINWINDOW_H
#include <QtCore/QVariant>
#include <QtWidgets/QAction>
#include <QtWidgets/QApplication>
#include <QtWidgets/QButtonGroup>
#include <QtWidgets/QHeaderView>
#include <QtWidgets/QMainWindow>
#include <QtWidgets/QMenuBar>
#include <QtWidgets/QPushButton>
#include <QtWidgets/QStatusBar>
#include <QtWidgets/QToolBar>
#include <QtWidgets/QWidget>
QT_BEGIN_NAMESPACE
class Ui_MainWindow
{
public:
QWidget *centralWidget;
QPushButton *pushButton;
QMenuBar *menuBar;
QToolBar *mainToolBar;
QStatusBar *statusBar;
void setupUi(QMainWindow *MainWindow)
{
if (MainWindow->objectName().isEmpty())
MainWindow->setObjectName(QStringLiteral("MainWindow"));
MainWindow->resize(393, 307);
centralWidget = new QWidget(MainWindow);
centralWidget->setObjectName(QStringLiteral("centralWidget"));
pushButton = new QPushButton(centralWidget);
pushButton->setObjectName(QStringLiteral("pushButton"));
pushButton->setGeometry(QRect(10, 10, 113, 32));
MainWindow->setCentralWidget(centralWidget);
menuBar = new QMenuBar(MainWindow);
menuBar->setObjectName(QStringLiteral("menuBar"));
menuBar->setGeometry(QRect(0, 0, 393, 22));
MainWindow->setMenuBar(menuBar);
mainToolBar = new QToolBar(MainWindow);
mainToolBar->setObjectName(QStringLiteral("mainToolBar"));
MainWindow->addToolBar(Qt::TopToolBarArea, mainToolBar);
statusBar = new QStatusBar(MainWindow);
statusBar->setObjectName(QStringLiteral("statusBar"));
MainWindow->setStatusBar(statusBar);
retranslateUi(MainWindow);
QObject::connect(pushButton, SIGNAL(released()), pushButton, SLOT(hide()));
QMetaObject::connectSlotsByName(MainWindow);
} // setupUi
void retranslateUi(QMainWindow *MainWindow)
{
MainWindow->setWindowTitle(QApplication::translate("MainWindow", "MainWindow", nullptr));
pushButton->setText(QApplication::translate("MainWindow", "Do not press", nullptr));
} // retranslateUi
};
namespace Ui {
class MainWindow: public Ui_MainWindow {};
} // namespace Ui
QT_END_NAMESPACE
#endif // UI_MAINWINDOW_H
I was able to migrate my real project to CMake with exactly one hiccup: the linker wasn't happy with any of the signal functions in my QObject-derived classes. (For those not familiar with Qt, a meta-object compiler, moc, magically converts certain empty functions marked as signals in a header file into real functions that the C++ compiler can use.) My conclusion is that both problems resulted from CMake not seeing the header files for a QObject-derived class, and so they were not sent to the moc in spite of the CMAKE_AUTOMOC setting.
The upshot is, if moc (or uic or rcc) needs to compile a file, then CMake has to know it exists before building any dependent targets. The crude solution I used for my project was to grep Q_OBJECT in the directory with all my header files, and copy/paste this list into a long set command in CMakeLists.txt
set(MOC_SOURCES
include/applewidget.h
include/borangewidget.h
...
)
and then add ${MOC_SOURCES} to my add_executable line. There may be a more sophisticated solution that involves building these objects separately, but my use of CMake has not yet reached that level of sophistication.
Meta object compiler (moc) generates moc_*.cpp files from headers. So the build system needs to know which headers to feed it. Similar to C++ compiler that needs to know which files to process. So when working with CMake and Qt you need to consider the header files as source files. CMake is smart enough to not ask C++ compiler to compile them so there's no harm in adding them for other libraries too.
Unfortunately neither Qt-CMake nor CMake-Qt documentation state this explicitly but you should always add headers to the list of sources in add_executable/add_library for CMAKE_AUTOMOC to work.
Another important thing is the minimal required version of CMake. CMake 2.6 does not support Qt5. Neither does CMake 2.8. The official Qt documentation claims the minimal CMake version to be 3.1.0. However CMake 3.0 already has Qt5 support. Still those version are way too old, slow, and buggy so consider updating the requirement. I'd recommend 3.11 or latest stable.

How resolve undefined reference to vtable in c++ on QT [duplicate]

This question already has answers here:
Qt Linker Error: "undefined reference to vtable" [duplicate]
(9 answers)
Closed 7 years ago.
i have Ubuntu 14.04 , C++ , QT ,
I will extend the class QPushbutton , and i will to make a new Slot
I do :
#include<QApplication>
#include<QDialog>
#include<QLabel>
#include <X11/Xlib.h>
#include<QVBoxLayout>
#include<iostream>
#include<QWidget>
#include<QPushButton>
#include <QThread>
#include <QGridLayout>
#include <QSplitter>
#include<QAbstractButton>
using namespace std;
class bot : public QPushButton {
Q_OBJECT;
public slots:
void txt() {
setText("hi");
}
};
int main(int a , char * b[])
{
QApplication application(a,b);
QPushButton *button = new QPushButton();
bot *l = new bot();
button->setFixedSize(100,100);
l->setText("sssssssssssssss");
QVBoxLayout *ll = new QVBoxLayout;
ll->addWidget(l);
ll->addWidget(button);
QWidget x ;
x.setLayout(ll);
x.show();
QObject::connect(button, SIGNAL(clicked()), l , SLOT( txt()) );
return application.exec();
}
The Problem is :
/home/user/untitled6/sd.cpp:18: error: undefined reference to `vtable
for bot'
how resolve the problem ???
my file.pro is :
SOURCES += \
sd.cpp
QT += widgets
FORMS += \
form.ui
Typically, errors like that can be resolved by running QMake. Anytime you create a new class that derives from QObject, Qt's model meta-object compiler (MOC) needs to auto-generate the code for the meta-class of the new class -- QMake ensures that this happens.
If you are using Qt Creator, just select Run qmake from the Build menu.
You may also have to run Clean project X or Clean all, also found in the Build menu.
The MOC can be temperamental, so you need to do the following:
Move your QObject-derived class into a separate source and header file (In your case, create bot.h and bot.cpp, and move the class code there)
Separate declaration and definition of your slot code (define txt as bot::txt in bot.cpp)
The MOC generates a corresponding meta-class file (moc_bot.cpp, in your case), and sometimes gets confused when there are multiple QObject-derived classes in one file. Best practice is to use one header and one source file for each QObject-derived class.
If all else fails, you may need to delete the .pro.user file for your project, and exit and restart Qt Creator. Then from Build menu, choose Clean all, Run qmake, Rebuild All.