Solved Linking error with qmlRegisterType
-
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]
-
Hi! Try "clean project", "run qmake" and then rebuild the project.
-
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 functionHow can I make setCounter visible?
Thanks,
Anthony -
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.
-
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.0ApplicationWindow {
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?
-
HI,
Use the "Topic Tools" button.
-
@att_ The Hitchhiker's Visual Guide to the Qt Forum explains how to mark threads as solved.