Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. App crashes using gadgets defined in a library
Forum Updated to NodeBB v4.3 + New Features

App crashes using gadgets defined in a library

Scheduled Pinned Locked Moved Unsolved QML and Qt Quick
2 Posts 1 Posters 118 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • M Offline
    M Offline
    mjakubowski
    wrote on 17 May 2023, 19:49 last edited by
    #1

    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

    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

    M 1 Reply Last reply 18 May 2023, 20:11
    0
    • M mjakubowski
      17 May 2023, 19:49

      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

      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

      M Offline
      M Offline
      mjakubowski
      wrote on 18 May 2023, 20:11 last edited by
      #2

      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.

      1 Reply Last reply
      1

      1/2

      17 May 2023, 19:49

      • Login

      • Login or register to search.
      1 out of 2
      • First post
        1/2
        Last post
      0
      • Categories
      • Recent
      • Tags
      • Popular
      • Users
      • Groups
      • Search
      • Get Qt Extensions
      • Unsolved