Stephane Wamba
Stephane Wamba

Reputation: 103

Undefined reference to MasterController::StaticMetaObject

I'm just starting learning Qt and currently I'm reading the book Learn Qt 5 by Nicolas Sheriff. Where I am, in chapter 2, I'm following all the instructions and I'M understanding what I am doing but i getting stuck on one thing: when i compile the following program along with others, I'm getting this list of errors:image shwowing the error messages

Here's the project structure

and the files I find worth showing are:

cm.pro file

QT       -= gui

TARGET = cm-lib
TEMPLATE = lib

CONFIG += c++17
DEFINES += CMLIB_LIBRARY
INCLUDEPATH += source

SOURCES += source/models/client.cpp \
           source/controllers/master-controller.cpp \

HEADERS += source/cm-lib_global.h \
           source/controllers/master-controller.h \
           source/models/client.h \

cm-lib.pro

QT       -= gui

TARGET = cm-lib
TEMPLATE = lib
CONFIG += c++17
DEFINES += CMLIB_LIBRARY
INCLUDEPATH += source

SOURCES += source/models/client.cpp \
           source/controllers/master-controller.cpp \

HEADERS += source/cm-lib_global.h \
           source/controllers/master-controller.h \
           source/models/client.h \

cm-ui.pro

QT += qml quick

TEMPLATE = app
CONFIG += c++17
INCLUDEPATH += source \
        ../cm-lib/source

SOURCES += source/main.cpp

RESOURCES += views.qrc
LIBS += -L$$PWD/../../build-cm-kit1-Debug/cm-lib/ -lcm-lib

MasterController.h

#ifndef MASTERCONTROLLER_H
#define MASTERCONTROLLER_H
#include <QObject>
#include <QString>
#include <cm-lib_global.h>

namespace cm::controllers {
class CMLIBSHARED_EXPORT MasterController : public QObject
{
    Q_OBJECT
    QString welcomeMessage = "This is MasterController to Major Tom";
    Q_PROPERTY( QString ui_welcomeMessage MEMBER welcomeMessage CONSTANT )
    public:
    explicit MasterController(QObject* parent = nullptr);
};
}

main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>

#include <controllers/master-controller.h>

int main(int argc, char *argv[])
{
    #if defined(Q_OS_WIN)
        QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    #endif

    QGuiApplication app(argc, argv);

    qmlRegisterType<cm::controllers::MasterController>("CM", 1, 0, "MasterController");

    cm::controllers::MasterController masterController{};

    QQmlApplicationEngine engine{};
    engine.rootContext()->setContextProperty("masterController", &masterController);
    engine.load(QUrl(QStringLiteral("qrc:/views/MasterView.qml")));

    if (engine.rootObjects().isEmpty())
        return -1;

    return app.exec();
}

It' long like that because I used the MVC design pattern here like in the book.

I think the problem is caused by the inclusion of the Q_OBJECT macro in MasterController.h because when I remove it, the project compile well without any issue.

After googling about the issue, on almost all the places I visited, the error was caused by the fact that the classes including Q_OBJECT macro would be declared in their own header file or qmake was not rerunned on these files including Q_OBJECT but It's not true in my case.

System tools used:

Upvotes: 6

Views: 8376

Answers (4)

avi14
avi14

Reputation: 1

I was getting same error for QWebSocketServer class.

was fixed by adding following line to .pro file

QT += websockets

Upvotes: 0

Michał Leon
Michał Leon

Reputation: 2316

Your code itself is OK and compiles, but you're missing a library in linking.

That's because you #include <QGuiApplication>, but you removed gui in thos line in your .pro:

QT       -= gui

Solution:

QT       += gui <and any other libraries you've used, e.g. bluetooth>

Upvotes: 0

Ingo Mi
Ingo Mi

Reputation: 1069

Simply change MEMBER to READ in the Q_PROPERTY solved this problem for me tho.

Took me hours :) You're welcome.

MasterController.h

    #ifndef MASTERCONTROLLER_H
    #define MASTERCONTROLLER_H
    #include <QObject>
    #include <QString>
    #include <cm-lib_global.h>

    namespace cm::controllers {
    class CMLIBSHARED_EXPORT MasterController : public QObject
    {
        Q_OBJECT
        QString welcomeMessage = "This is MasterController to Major Tom";
        Q_PROPERTY( QString ui_welcomeMessage READ welcomeMessage CONSTANT ) //<-----MEMBER to READ
        public:
        explicit MasterController(QObject* parent = nullptr);
    };
    }

Btw.: In the error message (of the screenshot you included in the question) you can right click and expand the message Show Output in the qt creator. Normally the error has a zickzackely underlining in there.

enter image description here

Upvotes: 0

Everlight
Everlight

Reputation: 126

The undefined reference is most likely caused by a missing moc file. When subclassing a qt object and using the Q_OBJECT macro the Qt Meta-Object Compiler creates a moc file (moc_master-controller.cpp) containing qobject related definitions including the missing staticMetaObject. This source file has to be compiled with the class definition. This is done automatically when using qmake.

Based on the code you provided your setup should be working. A few things to try:

  • Run qmake again. After adding or removing the Q_OBJECT macro qmake has to be run again. If you added Q_OBJECT after running qmake then the makefile does not contain the moc command for master-controller.h.
  • Make sure that the class is exported correctly from the lib and the other project finds the lib and imports correctly.
  • It is worth a try to do a clean and rebuild in case there was a problem during a previous build.

I tried reproducing the issue based on the code you provided but it compiled fine for me. In case you want to cross-reference with your code I've included mine below.

cm-lib.pro

QT       -= gui

TARGET = cm-lib
TEMPLATE = lib
CONFIG += c++17
DEFINES += CMLIB_LIBRARY
INCLUDEPATH += source

SOURCES += master-controller.cpp

HEADERS += cm-lib_global.h \
    master-controller.h

cm-lib_global.h

#pragma once

#include <QtCore/QtGlobal>

#if defined(CMLIB_LIBRARY)
#  define CMLIBSHARED_EXPORT Q_DECL_EXPORT
#else
#  define CMLIBSHARED_EXPORT Q_DECL_IMPORT
#endif

master-controller.h

#pragma once

#include <QObject>
#include <QString>
#include <cm-lib_global.h>

namespace cm::controllers {
class CMLIBSHARED_EXPORT MasterController : public QObject
{
    Q_OBJECT
    QString welcomeMessage = "This is MasterController to Major Tom";
    Q_PROPERTY( QString ui_welcomeMessage MEMBER welcomeMessage CONSTANT )
    public:
    explicit MasterController(QObject* parent = nullptr);
};
}

master-controller.cpp

#include "master-controller.h"

cm::controllers::MasterController::MasterController(QObject* parent):
    QObject(parent)
{
}

cm-ui.pro

QT += qml quick

TEMPLATE = app
CONFIG += c++17
INCLUDEPATH += ../cm-lib

SOURCES += main.cpp

LIBS += -L"../build-cm-lib-Desktop_Qt_5_12_1_MinGW_64_bit-Debug\debug" -lcm-lib

main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>

#include <master-controller.h>

int main(int argc, char *argv[])
{
    #if defined(Q_OS_WIN)
        QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    #endif

    QGuiApplication app(argc, argv);

    qmlRegisterType<cm::controllers::MasterController>("CM", 1, 0, "MasterController");

    cm::controllers::MasterController masterController{};

    QQmlApplicationEngine engine{};
    engine.rootContext()->setContextProperty("masterController", &masterController);
    engine.load(QUrl(QStringLiteral("qrc:/views/MasterView.qml")));

    if (engine.rootObjects().isEmpty())
        return -1;

    return app.exec();
}

Upvotes: 7

Related Questions