У меня проблема с передачей Q_PROPERTY
как QVariantMap
в QML - Ошибка сегментации.
Я создал простое приложение, чтобы показать проблему.
Когда я использую компилятор MinGW 11.2, все нормально, но проблема в Clang 15.0.4.
Я установил Clang от msys2 mingw-w64-x86_64-clang
и mingw-w64-clang-x86_64-toolchain
. Установка mingw-w64-clang-x86_64-qt6
тоже не помогла.
Набор:
Компилятор:
Ошибка:
Код:
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
}
}
}
Куча:
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
Это происходит, когда я нажимаю кнопку - поэтому, когда я пытаюсь использовать эту карту. Я также пробовал другую инициализацию карты (также ваше предложение), но безрезультатно.
Вы пытались отладить это? Согласно стеку вызовов, который происходит при получении свойства, а не при start()
. Кстати, попробуйте заменить testClass.testMap.t1
на testClass.testMap["t1"]
Да, я пробовал, но пока безрезультатно. Отладка показывает мне именно то, что я описал в посте.
У вас такой же segfault при вставке только одного элемента? (кажется надуманным, но кто знает)
К сожалению, такая же ошибка на 1 QV4::ExecutionEngine::newIdentifier qv4engine.cpp
Чтобы скомпилировать проект Qt с помощью CLang, вы должны сначала скомпилировать сам Qt с помощью CLang.
Для этого вам понадобится пара вещей. Во-первых, прочитайте этот исходный материал (я поставлю tl;dr ниже, но это может не сработать): https://doc.qt.io/qt-6/windows-building.html (для Linux и других, см.: https://doc.qt.io/qt-6/build-sources.html).
После установки всех зависимостей (таких как flex, bison и т. д.) перейдите в исходную папку (либо извлеченную из репозитория, либо загруженную вместе с установкой). Затем откройте выбранную среду (msys2, локальные установки, cmd или PowerShell).Войдите в каталог с исходными файлами и настройте шаг, например:
./configure -release -opensource -confirm-license -prefix <OUTPUT_FOLDER_OF_YOUR_CHOICE>
И ждать, пока он закончится. Затем соберите (по умолчанию) ниндзя:
ninja
- вы можете использовать переключатель -j
для большего количества заданий. (ninja -j6
)
И закончить с ninja install
. При этом вы сможете запускать CLang и qt с помощью... принуждения.
Примечание:
Команды:
./configure -release -opensource -confirm-license -prefix <OUTPUT_FOLDER_OF_YOUR_CHOICE>
ninja -j6
ninja install
Это боль. Когда произошел сбой? При запуске? Или когда вы нажали на кнопку? Для инициализации карты, как насчет того, чтобы вместо использования
insert
использовать перегрузку оператора, то естьtestMap["t1"] = QString("Mam 1");
?