8

So, I've done some searching and none of the similar questions I've read have had advice that worked.

I'm using Qt Creator (and I'm not too familiar with Qt) so I'm not sure what voodoo it's done in the background. However, I'm using a standard Qt Quick Application project.

Essentially, I want to call a C++ function from QML that returns a string that replaces some text in the layout, periodically.

Here is main.cpp:

#include <QtGui/QApplication>
#include "qmlapplicationviewer.h"
#include <QDeclarativeContext>


class testClass : public QObject
{
    Q_OBJECT
public:
    Q_INVOKABLE QString gimmeText() {
            return QString("new text");
}
};



Q_DECL_EXPORT int main(int argc, char *argv[])
{
    QScopedPointer<QApplication> app(createApplication(argc, argv));

    QmlApplicationViewer viewer;

    viewer.setOrientation(QmlApplicationViewer::ScreenOrientationAuto);
    viewer.setMainQmlFile(QLatin1String("qml/Picenter2/main.qml"));

    testClass t;
    viewer.rootContext()->setContextProperty("testOb", &t);

    viewer.showFullScreen();

    return app->exec();
}

And here is a snippet of the layout (as most of it is obviously irrelevant):

Text {
    id: text1
    x: 105
    y: 156
    color: "#ffffff"
    text: qsTr("text")
    font.pixelSize: 12
    Timer {
        interval: 1000; running: true; repeat: false
        onTriggered: text1.text = testOb.gimmeText();
    }

The errors given are:

invalid use of incomplete type 'struct QDeclarativeContext' main.cpp (28)
forward declaration of 'struct QDeclarativeContext' qdeclarativeview.h (60)

EDIT: with QDeclarativeContext included, the above disappear, giving these errors:

(.text.startup+0x3e):-1: error: undefined reference to `vtable for testClass'
(.text.startup+0xcf):-1: error: undefined reference to `vtable for testClass'
(.text.startup+0x12b):-1: error: undefined reference to `vtable for testClass'
:-1: error: collect2: ld returned 1 exit status

I haven't done much C++ programming, so I'm not entirely familiar with what that means. Following advice for essentially identical problems has only given me vtable errors or more incomprehensible things.

What really confuses me is that, looking at the header file, the QmlApplicationViewer is derived from QDeclarativeView, which is exactly what the Qt documentation uses here to do almost exactly what I want. Thanks for any suggestions anyone has.

Logan
  • 1,614
  • 1
  • 14
  • 27
  • The error message means, that the compiler knows, that there is a class called "QDeclarativeContext" but don't know the details needed to resolve a function call (for example). Lookup the header where that class is declared and include that header in your example. – Torsten Robitzki Dec 11 '12 at 07:53
  • That's what I'd read. So, I included it. It only gives me three 'undefined reference to `vtable for testClass' errors. – Logan Dec 11 '12 at 07:57
  • Are you sure, that you are linking correctly against the qt libraries and that the libraries are given in the correct order? – Torsten Robitzki Dec 11 '12 at 08:00
  • Not at all. I'm using Qt Creator, which does the linking for me. As for the libraries, I just tried switching "qmlapplicationviewer" and QDeclarativeContext and there was no change. – Logan Dec 11 '12 at 08:03
  • 3
    Ok, so the missing symbols steam from your own testClass. If I got it right, there is a special tools shipped with qt, that creates code from Q_OBJECT and Q_INVOKABLE macros. You should move the class into a separate header. Sounds creasy, but give it a try ;-) – Torsten Robitzki Dec 11 '12 at 08:06
  • 2
    `undefined reference to vtable` usually means that You need to rebuild project (make clean + qmake + make) – Dmitry Melnikov Dec 11 '12 at 08:11
  • 3
    It worked since `moc` application which generates code with meta data is run by make only for headers. Adding *.cpp file as header in *.pro file gives same effect (but this is nasty approach). – Marek R Dec 11 '12 at 09:25
  • Ahhh. Good to know. I really ought to learn more about code linking and makefiles, etc. I wonder why the Qt example worked... Anyway, Torsten, since you solved it first I'm waiting on you to make an answer so that I can accept it! haha – Logan Dec 11 '12 at 09:28

2 Answers2

5

You have to register your class for using it with QML. You can do this in the main function. You have to import it in the QML code too. Your code should look like this :

main.cpp :

#include <QtGui/QApplication>
#include "qmlapplicationviewer.h"
#include <QDeclarativeContext>

#include <QtDeclarative>    // Required for registration


class testClass : public QObject
{
    Q_OBJECT
    public:
    Q_INVOKABLE QString gimmeText() {
            return QString("new text");
    }
};



Q_DECL_EXPORT int main(int argc, char *argv[])
{
    QScopedPointer<QApplication> app(createApplication(argc, argv));

    qmlRegisterType<testClass>("MyCustomQMLObjects", 2, 35, "testClassNameInQML");

    QmlApplicationViewer viewer;

    viewer.setOrientation(QmlApplicationViewer::ScreenOrientationAuto);
    viewer.setMainQmlFile(QLatin1String("qml/Picenter2/main.qml"));

    testClass t;
    viewer.rootContext()->setContextProperty("testOb", &t);

    viewer.showFullScreen();

    return app->exec();
}

QML code :

// ...

import MyCustomQMLObjects 2.35

// ...

property testClassNameInQML testOb

// ...

Text {
    id: text1
    x: 105
    y: 156
    color: "#ffffff"
    text: qsTr("text")
    font.pixelSize: 12
    Timer {
        interval: 1000; running: true; repeat: false
        onTriggered: text1.text = testOb.gimmeText();
    }

// ...
air-dex
  • 4,130
  • 2
  • 25
  • 25
0

I have no experience with qt and I cant see what in the code triggers the error. However when such errors occur, it is because a class (struct QDeclarativeContext) has been forward declared, but is used as if the entire definition is known (access member, declare variable of this type, etc). To fix this you need to include the header which has this type's definition.

Karthik T
  • 31,456
  • 5
  • 68
  • 87