I have a problem with passing Q_PROPERTY
as QVariantMap
to QML - Segmentation fault.
I created simple app to show the problem.
When I'm using compiler MinGW 11.2 everything is fine, but the problem is under Clang 15.0.4.
I have installed Clang by msys2 mingw-w64-x86_64-clang
and mingw-w64-clang-x86_64-toolchain
. Installing mingw-w64-clang-x86_64-qt6
also didn't help.
Code:
main.cpp
#include "TestClass.h"
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
int main(int argc, char *argv[]) {
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
TestClass t;
engine.rootContext()->setContextProperty("testClass", &t);
const QUrl url(u"qrc:/QuickUI/qml/main.qml"_qs);
QObject::connect(
&engine, &QQmlApplicationEngine::objectCreated, &app,
[url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
},
Qt::QueuedConnection);
engine.load(url);
return app.exec();
}
TestClass.cpp
#pragma once
#include <QObject>
#include <QVariantMap>
#include <QDebug>
class TestClass : public QObject {
Q_OBJECT
Q_PROPERTY(QVariantMap testMap MEMBER testMap NOTIFY testMapChanged)
Q_PROPERTY(QString testStr MEMBER testStr NOTIFY testMapChanged)
public:
TestClass() : QObject() {}
QVariantMap testMap;
QString testStr = "test";
Q_INVOKABLE void start() {
qDebug() << "Kliknalem";
testMap.insert("t1", "Mam 1");
testMap.insert("t2", "Mam 2");
emit testMapChanged();
}
signals:
void testMapChanged();
};
main.qml
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
Window {
width: 640
height: 480
visible: true
title: qsTr("Hello World")
Rectangle {
anchors.fill: parent
color: "#FFFFFF"
}
ColumnLayout {
anchors.top: parent.top
anchors.left: parent.left
anchors.margins: 20
spacing: 20
Button {
Layout.preferredHeight: 30
Layout.fillWidth: true
text: "Klik"
onClicked: {
testClass.start();
}
}
Text {
text: testClass.testStr
}
Text {
text: testClass.testMap.t1
}
Text {
text: testClass.testMap.t2
}
}
}
Stack:
1 QV4::ExecutionEngine::newIdentifier
2 variantMapToJS
3 QV4::ExecutionEngine::fromData
4 QV4::ExecutionEngine::fromVariant
5 loadProperty
6 QV4::Moth::VME::interpret
7 QV4::Moth::VME::exec
8 QV4::Function::call
9 QQmlJavaScriptExpression::evaluate
10 QQmlBinding::evaluate
11 QQmlNonbindingBinding::doUpdate
12 QQmlBinding::update
13 QQmlNotifier::emitNotify
14 doActivate<false>
15 TestClass::start()
16 TestClass::qt_metacall(QMetaObject::Call, int, void * *)
17 QQmlObjectOrGadget::metacall
18 CallMethod
19 CallPrecise
20 operator()
21 operator()<QV4::QObjectMethod::callInternal(const QV4::Value *, const QV4::Value *, int) const::<lambda()>>
22 QV4::QObjectMethod::callInternal
23 QV4::FunctionObject::call
24 QV4::Moth::VME::interpret
25 QV4::Moth::VME::exec
26 QV4::Function::call
27 operator()
28 QV4::convertAndCall<QV4::Function::call(QObject *, void * *, const QMetaType *, int, QV4::ExecutionContext *)::<lambda(const QV4::Value *, const QV4::Value *, int)>>
29 QV4::Function::call
30 QQmlJavaScriptExpression::evaluate
31 QQmlBoundSignalExpression::evaluate
32 QQmlBoundSignal_callback
33 QQmlNotifier::emitNotify
34 doActivate<false>
35 QMetaObject::activate
36 QQuickAbstractButton::doubleClicked
37 QQuickAbstractButtonPrivate::handleRelease
38 QQuickControl::mouseReleaseEvent
39 QQuickItem::event
40 QCoreApplication::notifyInternal2
41 QCoreApplication::sendEvent
42 QQuickDeliveryAgentPrivate::deliverMatchingPointsToItem
43 QQuickDeliveryAgentPrivate::deliverUpdatedPoints
44 QQuickDeliveryAgentPrivate::deliverPointerEvent
45 QQuickDeliveryAgentPrivate::handleMouseEvent
46 QQuickDeliveryAgent::event
47 QQuickWindow::event
48 QCoreApplication::notifyInternal2
49 QCoreApplication::sendSpontaneousEvent
50 QGuiApplicationPrivate::processMouseEvent
51 QWindowSystemInterface::sendWindowSystemEvents
52 QEventDispatcherWin32::processEvents
53 QWindowsGuiEventDispatcher::processEvents
54 QEventLoop::processEvents
55 QEventLoop::exec
56 QCoreApplication::exec
57 qMain(int, char * *)
58 WinMain
59 main
60 __tmainCRTStartup
61 WinMainCRTStartup
To compile the Qt project with CLang, you must first compile the Qt itself with CLang.
To do this, you need a couple of things. First, read this source material (I will put tl;dr under, but it might not work): https://doc.qt.io/qt-6/windows-building.html (for Linux and others, refer to: https://doc.qt.io/qt-6/build-sources.html).
Once you have all dependencies (like flex, bison, etc., installed), proceed to your source folder (either checked out from the repo or downloaded with your installation. Then open the environment of choice (msys2, local installs, cmd, or PowerShell). Enter the directory with source files and configure step, for example:
./configure -release -opensource -confirm-license -prefix <OUTPUT_FOLDER_OF_YOUR_CHOICE>
And wait for it to end. Then build with (by default) ninja:
ninja
- you can use -j
switch for more jobs. (ninja -j6
)
And finish up with ninja install
. With this, you should be able to run your CLang and qt by... coercion.
Note:
Commands:
./configure -release -opensource -confirm-license -prefix <OUTPUT_FOLDER_OF_YOUR_CHOICE>
ninja -j6
ninja install