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
Forum Updated to NodeBB v4.3 + New Features

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