Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. Linking error with qmlRegisterType
Qt 6.11 is out! See what's new in the release blog

Linking error with qmlRegisterType

Scheduled Pinned Locked Moved Solved QML and Qt Quick
7 Posts 4 Posters 3.4k Views 3 Watching
  • 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.
  • A Offline
    A Offline
    att_
    wrote on last edited by kshegunov
    #1

    Hi all,

    I am learning exchanging data between qml and C++ class. So I write this simple test program.

    I wrote a simple QML file

    import QtQuick 2.7
    import QtQuick.Controls 2.0
    import QtQuick.Layouts 1.0
    
    //import testing 1.0
    
    ApplicationWindow {
        visible: true
        width: 640
        height: 480
        title: qsTr("Hello World")
    
        property string count: "hello"
    
        Rectangle
        {
            width: parent.width
            height: parent.height
            Text {
                id: text
                text: qsTr("text")
                anchors.horizontalCenter: parent.horizontalCenter
                anchors.verticalCenter: parent.verticalCenter
            }
        }
        MouseArea
        {
            anchors.fill: parent
            onClicked:
            {
                console.log("count " + count)
            }
        }
    }
    

    and simple main.cpp

    #include <QGuiApplication>
    #include <QQmlApplicationEngine>
    #include "updatecounter.h"
    
    int main(int argc, char *argv[])
    {
        QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
        QGuiApplication app(argc, argv);
    
    //    qmlRegisterType<UpdateCounter>("testing", 1, 0, "UpdateCounter");
    
        QQmlApplicationEngine engine;
        engine.load(QUrl(QLatin1String("qrc:/main.qml")));
    
        return app.exec();
    }
    

    Everything is fine up to here. Then I added my C++ class

    #ifndef UPDATECOUNTER_H
    #define UPDATECOUNTER_H
    
    #include <QObject>
    
    class UpdateCounter : public QObject
    {
        Q_OBJECT
        Q_PROPERTY(QString counter READ counter WRITE setCounter NOTIFY counterChanged)
    public:
        explicit UpdateCounter(QObject *parent = 0);
    
        QString counter() const {return mcounter;}
        void setCounter(const QString &counter);
        Q_INVOKABLE void sendCounterUpdate(const QString &counter);
    
    signals:
        void counterChanged();
    
    private:
        QString mcounter;
    };
    
    #endif // UPDATECOUNTER_H
    
    #include "updatecounter.h"
    
    UpdateCounter::UpdateCounter(QObject *parent) : QObject(parent)
    {
    
    }
    
    void UpdateCounter::setCounter(const QString &counter)
    {
        if(counter == mcounter)
            return;
        mcounter = counter;
    }
    
    void UpdateCounter::sendCounterUpdate(const QString &counter)
    {
        if(counter == mcounter)
            return;
        mcounter = counter;
        emit counterChanged();
    }
    

    The program behaves as expected. Then I register my class using qmlRegisterType. I get linking errors.

    main.obj:-1: error: LNK2001: unresolved external symbol "public: virtual struct QMetaObject const * __cdecl UpdateCounter::metaObject(void)const " (?metaObject@UpdateCounter@@UEBAPEBUQMetaObject@@XZ)
    main.obj:-1: error: LNK2001: unresolved external symbol "public: virtual void * __cdecl UpdateCounter::qt_metacast(char const *)" (?qt_metacast@UpdateCounter@@UEAAPEAXPEBD@Z)
    main.obj:-1: error: LNK2001: unresolved external symbol "public: virtual int __cdecl UpdateCounter::qt_metacall(enum QMetaObject::Call,int,void * *)" (?qt_metacall@UpdateCounter@@UEAAHW4Call@QMetaObject@@HPEAPEAX@Z)
    main.obj:-1: error: LNK2019: unresolved external symbol "public: __cdecl UpdateCounter::UpdateCounter(class QObject *)" (??0UpdateCounter@@QEAA@PEAVQObject@@@Z) referenced in function "public: __cdecl QQmlPrivate::QQmlElement<class UpdateCounter>::QQmlElement<class UpdateCounter>(void)" (??0?$QQmlElement@VUpdateCounter@@@QQmlPrivate@@QEAA@XZ)
    main.obj:-1: error: LNK2001: unresolved external symbol "public: static struct QMetaObject const UpdateCounter::staticMetaObject" (?staticMetaObject@UpdateCounter@@2UQMetaObject@@B)
    

    Please let me know what I did wrong.

    Thank you,
    Anthony

    [Added code tags ~kshegunov]

    1 Reply Last reply
    0
    • ? Offline
      ? Offline
      A Former User
      wrote on last edited by
      #2

      Hi! Try "clean project", "run qmake" and then rebuild the project.

      1 Reply Last reply
      2
      • A Offline
        A Offline
        att_
        wrote on last edited by
        #3

        Thank you. I have to remember to do that all the time.

        Now I have a different error. I have
        declared setCounter in the .h file
        Q_PROPERTY(QString counter READ counter WRITE setCounter NOTIFY counterChanged)
        void setCounter(const QString &counter);

        implemented the code in the cpp file
        void UpdateCounter::setCounter(const QString &counter)
        {
        if(counter == mcounter)
        return;
        mcounter = counter;
        }
        registered the class in main.cpp
        qmlRegisterType<UpdateCounter>("testing", 1, 0, "UpdateCounter");

        imported the class and assigned an object in qml
        import testing 1.0
        UpdateCounter{id: updateCounter}

        But when I call the function I get this error at run time.
        updateCounter.setCounter(count)
        qrc:/main.qml:33: TypeError: Property 'setCounter' of object [object Object] is not a function

        How can I make setCounter visible?

        Thanks,
        Anthony

        1 Reply Last reply
        0
        • dheerendraD Offline
          dheerendraD Offline
          dheerendra
          Qt Champions 2022
          wrote on last edited by
          #4

          setCounter cannot be called directly. Either make the setCounter(..) function as Q_INVOKABLE or move the function under slot. It will be called. Looking at your code you idea is to set the value of counter. Since counter is exposed via Q_PROPERTY directly set it like updateCounter.counter = 10. Now setCounter function will be called automatically.

          Dheerendra
          @Community Service
          Certified Qt Specialist
          http://www.pthinks.com

          1 Reply Last reply
          5
          • A Offline
            A Offline
            att_
            wrote on last edited by
            #5

            Thank you for your advices. It works now. I achieved what I want to do. Here is the code for anyone interested.

            H file
            class UpdateCounter : public QObject
            {
            Q_OBJECT
            Q_PROPERTY(double counter READ counter WRITE setCounter NOTIFY counterChanged)
            public:
            double counter() const {return mcounter;}
            void setCounter(const double);

            Q_INVOKABLE void resetCounter(const double);
            

            signals:
            void counterChanged();

            private:
            double mcounter;
            };

            CPP file
            void UpdateCounter::setCounter(const double counter)
            {
            if(counter == mcounter)
            return;
            qDebug() << "UpdateCounter.setCounter" << counter;
            mcounter = counter + 2;
            emit counterChanged();
            }

            void UpdateCounter::resetCounter(const double counter)
            {
            if(counter == mcounter)
            return;
            qDebug() << "UpdateCounter.resetCounter" << counter;
            mcounter = counter;
            emit counterChanged();
            }

            int main(int argc, char *argv[])
            {
            QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
            QGuiApplication app(argc, argv);

            qmlRegisterType<UpdateCounter>("testing", 1, 0, "UpdateCounter");
            
            QQmlApplicationEngine engine;
            engine.load(QUrl(QLatin1String("qrc:/main.qml")));
            
            return app.exec();
            

            }

            and qml file
            import testing 1.0

            ApplicationWindow {
            visible: true
            width: 640
            height: 480
            title: qsTr("Hello World")

            property double count: 0
            UpdateCounter
            {
                id: updateCounter
                onCounterChanged:
                {
                    count = counter;
                    console.log("QML UpdateCounter " + count)
                    text.text = qsTr("Counter %1").arg(count)
                }
            }
            
            Rectangle
            {
                width: parent.width
                height: parent.height/2
                color: "red"
                Text
                {
                    text: qsTr("Reset")
                    anchors.horizontalCenter: parent.horizontalCenter
                    anchors.verticalCenter: parent.verticalCenter
                }
                MouseArea
                {
                    anchors.fill: parent
                    onClicked:
                    {
                        console.log("QML reset to 10 " + count)
                        updateCounter.resetCounter(10)
                    }
                }
            }
            Rectangle
            {
                y: parent.height/2
                width: parent.width
                height: parent.height/2
                color: "yellow"
                Text
                {
                    id: text
                    text: qsTr("text")
                    anchors.horizontalCenter: parent.horizontalCenter
                    anchors.verticalCenter: parent.verticalCenter
                }
                MouseArea
                {
                    anchors.fill: parent
                    onClicked:
                    {
                        console.log("QML count " + count)
                        count = count + 1
                        updateCounter.counter = count
                    }
                }
            }
            

            }

            now how do I mark this topic as solved?

            ? 1 Reply Last reply
            0
            • SGaistS Offline
              SGaistS Offline
              SGaist
              Lifetime Qt Champion
              wrote on last edited by
              #6

              HI,

              Use the "Topic Tools" button.

              Interested in AI ? www.idiap.ch
              Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

              1 Reply Last reply
              0
              • A att_

                Thank you for your advices. It works now. I achieved what I want to do. Here is the code for anyone interested.

                H file
                class UpdateCounter : public QObject
                {
                Q_OBJECT
                Q_PROPERTY(double counter READ counter WRITE setCounter NOTIFY counterChanged)
                public:
                double counter() const {return mcounter;}
                void setCounter(const double);

                Q_INVOKABLE void resetCounter(const double);
                

                signals:
                void counterChanged();

                private:
                double mcounter;
                };

                CPP file
                void UpdateCounter::setCounter(const double counter)
                {
                if(counter == mcounter)
                return;
                qDebug() << "UpdateCounter.setCounter" << counter;
                mcounter = counter + 2;
                emit counterChanged();
                }

                void UpdateCounter::resetCounter(const double counter)
                {
                if(counter == mcounter)
                return;
                qDebug() << "UpdateCounter.resetCounter" << counter;
                mcounter = counter;
                emit counterChanged();
                }

                int main(int argc, char *argv[])
                {
                QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
                QGuiApplication app(argc, argv);

                qmlRegisterType<UpdateCounter>("testing", 1, 0, "UpdateCounter");
                
                QQmlApplicationEngine engine;
                engine.load(QUrl(QLatin1String("qrc:/main.qml")));
                
                return app.exec();
                

                }

                and qml file
                import testing 1.0

                ApplicationWindow {
                visible: true
                width: 640
                height: 480
                title: qsTr("Hello World")

                property double count: 0
                UpdateCounter
                {
                    id: updateCounter
                    onCounterChanged:
                    {
                        count = counter;
                        console.log("QML UpdateCounter " + count)
                        text.text = qsTr("Counter %1").arg(count)
                    }
                }
                
                Rectangle
                {
                    width: parent.width
                    height: parent.height/2
                    color: "red"
                    Text
                    {
                        text: qsTr("Reset")
                        anchors.horizontalCenter: parent.horizontalCenter
                        anchors.verticalCenter: parent.verticalCenter
                    }
                    MouseArea
                    {
                        anchors.fill: parent
                        onClicked:
                        {
                            console.log("QML reset to 10 " + count)
                            updateCounter.resetCounter(10)
                        }
                    }
                }
                Rectangle
                {
                    y: parent.height/2
                    width: parent.width
                    height: parent.height/2
                    color: "yellow"
                    Text
                    {
                        id: text
                        text: qsTr("text")
                        anchors.horizontalCenter: parent.horizontalCenter
                        anchors.verticalCenter: parent.verticalCenter
                    }
                    MouseArea
                    {
                        anchors.fill: parent
                        onClicked:
                        {
                            console.log("QML count " + count)
                            count = count + 1
                            updateCounter.counter = count
                        }
                    }
                }
                

                }

                now how do I mark this topic as solved?

                ? Offline
                ? Offline
                A Former User
                wrote on last edited by
                #7

                @att_ The Hitchhiker's Visual Guide to the Qt Forum explains how to mark threads as solved.

                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