英文:
Qt QML app crashing using gadgets defined in a library
问题
在你提供的代码和描述中,问题似乎出现在你尝试使用QML中的obj.bar.x
时,应用程序崩溃,而不是obj.foo.x
。根据你提供的信息,这可能是由于Bar
类型没有正确注册为Qt元类型而引起的。
为了正确注册Bar
类型,你可以在foo
项目的代码中添加以下行:
#include <QMetaType>
Q_DECLARE_METATYPE(Bar)
然后,在main.cpp
的main
函数之前,添加以下行,以确保Bar
类型在使用前已注册:
qRegisterMetaType<Bar>();
这应该解决你遇到的问题,因为它会正确注册Bar
类型,以便在QML中使用它。如果问题仍然存在,可能需要仔细检查项目的配置和代码,确保没有其他问题导致崩溃。
英文:
Given two CMake subprojects: foo and bar, I want to define Q_GADGET in bar and use it in foo, but the application crashes when accessing a QObject property of type Bar (defined in bar project).
foo CMakeLists, created by QtCreator, I just added SOURCES / HEADER and added bar
to target_link_libraries
:
cmake_minimum_required(VERSION 3.16)
project(foo VERSION 0.1 LANGUAGES CXX)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(Qt6 6.5 REQUIRED COMPONENTS Quick)
qt_standard_project_setup(REQUIRES 6.5)
set(SOURCES
# cmake-format: sort
main.cpp
foo.cpp
fooobjectwithbarproperty.cpp
)
set(HEADER
# cmake-format: sort
fooobjectwithbarproperty.h
foo.h
)
qt_add_executable(appfoo
main.cpp
)
qt_add_qml_module(appfoo
URI foo
VERSION 1.0
QML_FILES Main.qml
SOURCES
${SOURCES}
${HEADER}
)
set_target_properties(appfoo PROPERTIES
MACOSX_BUNDLE_GUI_IDENTIFIER my.example.com
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
MACOSX_BUNDLE TRUE
WIN32_EXECUTABLE TRUE
)
target_link_libraries(appfoo
PUBLIC Qt6::Quick bar
)
install(TARGETS appfoo
BUNDLE DESTINATION .
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
bar CMakeLists:
cmake_minimum_required(VERSION 3.14)
project(bar LANGUAGES CXX)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core)
add_library(bar SHARED
bar_global.h
bar.cpp
bar.h
)
target_link_libraries(bar PRIVATE Qt${QT_VERSION_MAJOR}::Core)
target_compile_definitions(bar PRIVATE BAR_LIBRARY)
top-level CMakeLists:
cmake_minimum_required(VERSION 3.26.0)
project(
FooBar
VERSION 0.0.1
DESCRIPTION "Demo for Qt issue"
LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
add_subdirectory(foo)
add_subdirectory(bar)
My QObject, defined in foo, looks like this:
class FooObjectWithBarProperty : public QObject
{
Q_OBJECT
Q_PROPERTY(Bar bar READ getBar WRITE setBar NOTIFY barChanged)
Q_PROPERTY(Foo foo READ getFoo WRITE setFoo NOTIFY fooChanged)
public:
const Bar getBar() const {
return _bar;
}
void setBar(const Bar& bar) {
_bar = bar;
emit barChanged(_bar);
}
const Foo getFoo() const {
return _foo;
}
void setFoo(const Foo& foo) {
_foo = foo;
emit fooChanged(_foo);
}
private:
Bar _bar;
Foo _foo;
signals:
void barChanged(const Bar&);
void fooChanged(const Foo&);
};
Foo is defined in foo, while Bar is defined in Bar, they both look exactly the same:
struct Foo
{
Q_GADGET
Q_PROPERTY(double x MEMBER x)
Q_PROPERTY(double y MEMBER y)
public:
double x, y;
};
Given the following setup in main.cpp:
QQmlApplicationEngine engine;
engine.rootContext()->setContextProperty("obj", new FooObjectWithBarProperty());
I added a Text item into my Main.qml that looks like this:
Text {
anchors.centerIn: parent
text: obj.foo.x
}
This correctly displays 0. If I change the binding too obj.bar.x the app crashes:
Stacktrace here suggest the metatype for Bar is not correctly registered, but I don't know how to correctly register it. I've tried qRegisterMetaType<Bar>, Q_DECLARE_METATYPE(Bar) in both foo or bar, I experimented a bit with QML_FOREIGN, but the docs are very sparse on it. All to no avail.
What is the necessary change here, and why?
Repo for this is available at https://github.com/marcinjakubowski/foo_bar_qt_issue
答案1
得分: 0
由于bar的CMakeLists文件中的这行代码:
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core)
它会寻找Qt6和Qt5,并且由于某些原因选择了Qt5来生成moc(元对象编译器)文件,这也可以从生成的moc_bar.cpp文件中看出:
/****************************************************************************
** Meta object code from reading C++ file 'bar.h'
**
** Created by: The Qt Meta Object Compiler version 67 (Qt 5.15.9)
将这行代码中的Qt5移除然后重新构建项目,问题就解决了。
英文:
As it turns out, it's because of this line in bar's CMakeLists:
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core)
It looks for Qt6 and Qt5, and, for some reason, picks Qt5 to generate moc files, as evidenced by the resulting moc_bar.cpp:
/****************************************************************************
** Meta object code from reading C++ file 'bar.h'
**
** Created by: The Qt Meta Object Compiler version 67 (Qt 5.15.9)
Removing Qt5 from that find_package call and rebuilding the project makes it all work fine.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论