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. How to expose a normal function to QML?
Forum Updated to NodeBB v4.3 + New Features

How to expose a normal function to QML?

Scheduled Pinned Locked Moved QML and Qt Quick
11 Posts 5 Posters 912 Views 4 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.
  • SavizS Offline
    SavizS Offline
    Saviz
    wrote last edited by
    #1

    I’m working on a database project written in C that exposes many plain C functions for running queries. We’re now building a QML front end and I want the simplest, lowest-effort way to integrate the two.

    I’ve seen forum posts recommending middleware classes that use the Q_OBJECT macro and Q_INVOKABLE methods, registered with the QML engine. Before I commit to writing hundreds of thin wrapper classes, is there a way to call plain, non-class member C functions directly from QML? (These functions aren’t attached to any class.)

    jeremy_kJ JKSHJ 2 Replies Last reply
    0
    • mzimmersM Offline
      mzimmersM Offline
      mzimmers
      wrote last edited by
      #2

      Qt is intended to be used by C++, not C. The macros you mentioned are intended for classes derived from QObject. Can you convert your project to C++, or at least create a hybrid C/C++ project so you can instantiate Qt classes?

      1 Reply Last reply
      0
      • SavizS Saviz

        I’m working on a database project written in C that exposes many plain C functions for running queries. We’re now building a QML front end and I want the simplest, lowest-effort way to integrate the two.

        I’ve seen forum posts recommending middleware classes that use the Q_OBJECT macro and Q_INVOKABLE methods, registered with the QML engine. Before I commit to writing hundreds of thin wrapper classes, is there a way to call plain, non-class member C functions directly from QML? (These functions aren’t attached to any class.)

        jeremy_kJ Offline
        jeremy_kJ Offline
        jeremy_k
        wrote last edited by
        #3

        @Saviz said in How to expose a normal function to QML?:

        I’m working on a database project written in C that exposes many plain C functions for running queries. We’re now building a QML front end and I want the simplest, lowest-effort way to integrate the two.

        I’ve seen forum posts recommending middleware classes that use the Q_OBJECT macro and Q_INVOKABLE methods, registered with the QML engine. Before I commit to writing hundreds of thin wrapper classes, is there a way to call plain, non-class member C functions directly from QML? (These functions aren’t attached to any class.)

        Does the function return a value? A there cleanup function or other funtions that can map to transitions in a UI?

        While Q_INVOKABLE almost certainly involves the least code to implement, use usually doesn't fit in with the declarative style of QML. Needing a hundreds of imperative functions sounds like a design in need of better compartmentalization of logic.

        Asking a question about code? http://eel.is/iso-c++/testcase/

        KH-219DesignK 1 Reply Last reply
        0
        • jeremy_kJ jeremy_k

          @Saviz said in How to expose a normal function to QML?:

          I’m working on a database project written in C that exposes many plain C functions for running queries. We’re now building a QML front end and I want the simplest, lowest-effort way to integrate the two.

          I’ve seen forum posts recommending middleware classes that use the Q_OBJECT macro and Q_INVOKABLE methods, registered with the QML engine. Before I commit to writing hundreds of thin wrapper classes, is there a way to call plain, non-class member C functions directly from QML? (These functions aren’t attached to any class.)

          Does the function return a value? A there cleanup function or other funtions that can map to transitions in a UI?

          While Q_INVOKABLE almost certainly involves the least code to implement, use usually doesn't fit in with the declarative style of QML. Needing a hundreds of imperative functions sounds like a design in need of better compartmentalization of logic.

          KH-219DesignK Offline
          KH-219DesignK Offline
          KH-219Design
          wrote last edited by
          #4

          @jeremy_k said in How to expose a normal function to QML?:

          Needing a hundreds of imperative functions sounds like a design in need of better compartmentalization of logic.

          @jeremy_k , please note that @Saviz is dealing with a "plain C" codebase. There are essentially no other options but imperative functions available under that scenario.

          I'm subscribed to this question/thread because I am also interested if others have found "the shortest path" (more specifically: the most concise path) to wrapping a free function for QML.

          Use of a C++ object will most likely be required (but again: I, too, await any insights from others, since I have not explored this topic in depth).

          However, one bit of good news may be the possibility to use a C++ object that does not inherit QObject. That could be possible via the "q_gadget" concept: https://doc.qt.io/qt-6/qobject.html#Q_GADGET

          per the prior link: "Q_GADGETs can have Q_ENUM, Q_PROPERTY and Q_INVOKABLE, but they cannot have signals or slots."

          www.219design.com
          Software | Electrical | Mechanical | Product Design

          jeremy_kJ SavizS 2 Replies Last reply
          1
          • KH-219DesignK KH-219Design

            @jeremy_k said in How to expose a normal function to QML?:

            Needing a hundreds of imperative functions sounds like a design in need of better compartmentalization of logic.

            @jeremy_k , please note that @Saviz is dealing with a "plain C" codebase. There are essentially no other options but imperative functions available under that scenario.

            I'm subscribed to this question/thread because I am also interested if others have found "the shortest path" (more specifically: the most concise path) to wrapping a free function for QML.

            Use of a C++ object will most likely be required (but again: I, too, await any insights from others, since I have not explored this topic in depth).

            However, one bit of good news may be the possibility to use a C++ object that does not inherit QObject. That could be possible via the "q_gadget" concept: https://doc.qt.io/qt-6/qobject.html#Q_GADGET

            per the prior link: "Q_GADGETs can have Q_ENUM, Q_PROPERTY and Q_INVOKABLE, but they cannot have signals or slots."

            jeremy_kJ Offline
            jeremy_kJ Offline
            jeremy_k
            wrote last edited by jeremy_k
            #5

            @KH-219Design said in How to expose a normal function to QML?:

            @jeremy_k said in How to expose a normal function to QML?:

            Needing a hundreds of imperative functions sounds like a design in need of better compartmentalization of logic.

            @jeremy_k , please note that @Saviz is dealing with a "plain C" codebase. There are essentially no other options but imperative functions available under that scenario.

            As @mzimmers noted, there is no support for Q_INVOKABLE outside of a QObject or Q_GADGET C++ class. I think it's reasonable to presume that OP and the general audience will understand as much at this point in the conversation.

            Once we are at that point, it's wise to consider other mechanisms to ease the burden.

            Asking a question about code? http://eel.is/iso-c++/testcase/

            1 Reply Last reply
            0
            • KH-219DesignK KH-219Design

              @jeremy_k said in How to expose a normal function to QML?:

              Needing a hundreds of imperative functions sounds like a design in need of better compartmentalization of logic.

              @jeremy_k , please note that @Saviz is dealing with a "plain C" codebase. There are essentially no other options but imperative functions available under that scenario.

              I'm subscribed to this question/thread because I am also interested if others have found "the shortest path" (more specifically: the most concise path) to wrapping a free function for QML.

              Use of a C++ object will most likely be required (but again: I, too, await any insights from others, since I have not explored this topic in depth).

              However, one bit of good news may be the possibility to use a C++ object that does not inherit QObject. That could be possible via the "q_gadget" concept: https://doc.qt.io/qt-6/qobject.html#Q_GADGET

              per the prior link: "Q_GADGETs can have Q_ENUM, Q_PROPERTY and Q_INVOKABLE, but they cannot have signals or slots."

              SavizS Offline
              SavizS Offline
              Saviz
              wrote last edited by
              #6

              @KH-219Design Thank you for taking my concern seriously. I’m surprised this topic isn’t covered in more depth.

              It feels unreasonable that exposing a simple function to QML requires such a rigid, inconvenient structure. Why does everything need to be a class and include some kind of Q_OBJECT / Q_GADET macro ? If that’s truly the only option, I may have to consider alternatives to QML. It would be simply too much work to create layers just for exposing these functions to the GUI.

              mzimmersM jeremy_kJ 2 Replies Last reply
              0
              • KH-219DesignK Offline
                KH-219DesignK Offline
                KH-219Design
                wrote last edited by
                #7

                database project written in C that exposes many plain C functions for running queries.

                (bold-font emphasis is my own)

                Yes. I empathize.

                A lot hinges on the magnitude of your "many" quantifier in the original problem description.

                I suspect that beyond some threshold it would be reasonable to write an automated wrapper-generator system rather than wrap each C header manually. For loose inspiration on wrapper-generator systems, I'm thinking something like ctypes (C-to-python) or QMetaObject-rs (Rust-to-QML).

                Come to think of it, maybe you could use ctypes to go from C to Python, then use PySide (Qt Python) for the GUI?** That's still a non-zero amount of work, but I give it pretty favorable odds of being less work than wrapping all your C for Q_GADGET. I guess the trade-off is roughly that you would end up with py files as your "glue" between C and QML, instead of C++ files as your glue between C and QML. Pick your poison? 🧪🧙😈

                **It isn't incredibly well known, but a GUI in PySide is perfectly able to support QML.

                www.219design.com
                Software | Electrical | Mechanical | Product Design

                1 Reply Last reply
                1
                • SavizS Saviz

                  @KH-219Design Thank you for taking my concern seriously. I’m surprised this topic isn’t covered in more depth.

                  It feels unreasonable that exposing a simple function to QML requires such a rigid, inconvenient structure. Why does everything need to be a class and include some kind of Q_OBJECT / Q_GADET macro ? If that’s truly the only option, I may have to consider alternatives to QML. It would be simply too much work to create layers just for exposing these functions to the GUI.

                  mzimmersM Offline
                  mzimmersM Offline
                  mzimmers
                  wrote last edited by mzimmers
                  #8

                  @Saviz said in How to expose a normal function to QML?:

                  It feels unreasonable that exposing a simple function to QML requires such a rigid, inconvenient structure. Why does everything need to be a class and include some kind of Q_OBJECT / Q_GADET macro ? If that’s truly the only option, I may have to consider alternatives to QML. It would be simply too much work to create layers just for exposing these functions to the GUI.

                  That's not an uncommon sentiment among people who are evaluating Qt (and in all candor, is likely one of the reasons Qt doesn't have a broader following). Qt is definitely not a "toe in the water" framework; it's more a "hold your nose and jump in" deal. If your C functions truly measure in the hundreds, you are indeed looking at a big interface layer, though it could probably be handled in a single (large) controller object.

                  But yeah...Qt might not be the right tool for your application.

                  1 Reply Last reply
                  1
                  • SavizS Saviz

                    @KH-219Design Thank you for taking my concern seriously. I’m surprised this topic isn’t covered in more depth.

                    It feels unreasonable that exposing a simple function to QML requires such a rigid, inconvenient structure. Why does everything need to be a class and include some kind of Q_OBJECT / Q_GADET macro ? If that’s truly the only option, I may have to consider alternatives to QML. It would be simply too much work to create layers just for exposing these functions to the GUI.

                    jeremy_kJ Offline
                    jeremy_kJ Offline
                    jeremy_k
                    wrote last edited by
                    #9

                    @Saviz said in How to expose a normal function to QML?:

                    @KH-219Design Thank you for taking my concern seriously. I’m surprised this topic isn’t covered in more depth.

                    It feels unreasonable that exposing a simple function to QML requires such a rigid, inconvenient structure. Why does everything need to be a class and include some kind of Q_OBJECT / Q_GADET macro ? If that’s truly the only option, I may have to consider alternatives to QML. It would be simply too much work to create layers just for exposing these functions to the GUI.

                    QML = Qt Meta-object Language.
                    The meta-object system enables transforming strings in the QML source text into properties (including functions) in a C++ object at runtime. Q_OBJECT and Q_GADGET macros expand into support code, and tell moc to generate corresponding meta-objects.

                    Perhaps you can get what you seek from the javascript engine. I've never felt the need to investigate that route.

                    Asking a question about code? http://eel.is/iso-c++/testcase/

                    1 Reply Last reply
                    0
                    • SavizS Saviz

                      I’m working on a database project written in C that exposes many plain C functions for running queries. We’re now building a QML front end and I want the simplest, lowest-effort way to integrate the two.

                      I’ve seen forum posts recommending middleware classes that use the Q_OBJECT macro and Q_INVOKABLE methods, registered with the QML engine. Before I commit to writing hundreds of thin wrapper classes, is there a way to call plain, non-class member C functions directly from QML? (These functions aren’t attached to any class.)

                      JKSHJ Offline
                      JKSHJ Offline
                      JKSH
                      Moderators
                      wrote last edited by JKSH
                      #10

                      @Saviz said in How to expose a normal function to QML?:

                      Before I commit to writing hundreds of thin wrapper classes, is there a way to call plain, non-class member C functions directly from QML? (These functions aren’t attached to any class.)

                      1. As others have pointed out, at least one class with Q_OBJECT or Q_GADGET is required.
                      2. You don't need hundreds of classes. You just need one class to hold your many methods/functions (or perhaps a few classes, if you want to organize/group your functions)
                      3. Do you need to expose every single C function directly to your GUI? Perhaps you could design your wrapper class as an abstraction layer that exposes fewer but higher-level methods to QML, while these higher-level functions each call multiple lower-level C functions.
                      4. If you do want to expose hundreds of C functions directly to QML, then it could make sense to write a wrapper script to read your C header and generate the corresponding wrapper C++ method.

                      Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

                      SavizS 1 Reply Last reply
                      3
                      • JKSHJ JKSH

                        @Saviz said in How to expose a normal function to QML?:

                        Before I commit to writing hundreds of thin wrapper classes, is there a way to call plain, non-class member C functions directly from QML? (These functions aren’t attached to any class.)

                        1. As others have pointed out, at least one class with Q_OBJECT or Q_GADGET is required.
                        2. You don't need hundreds of classes. You just need one class to hold your many methods/functions (or perhaps a few classes, if you want to organize/group your functions)
                        3. Do you need to expose every single C function directly to your GUI? Perhaps you could design your wrapper class as an abstraction layer that exposes fewer but higher-level methods to QML, while these higher-level functions each call multiple lower-level C functions.
                        4. If you do want to expose hundreds of C functions directly to QML, then it could make sense to write a wrapper script to read your C header and generate the corresponding wrapper C++ method.
                        SavizS Offline
                        SavizS Offline
                        Saviz
                        wrote last edited by
                        #11

                        @JKSH said in How to expose a normal function to QML?:

                        Do you need to expose every single C function directly to your GUI? Perhaps you could design your wrapper class as an abstraction layer that exposes fewer but higher-level methods to QML, while these higher-level functions each call multiple lower-level C functions.

                        You are absolutely right that not all functions need to be exposed to the GUI layer. However, there are still a significant number of functions that do need to be invoked directly from the GUI. For that reason, I believe your proposed solution of creating a controller or wrapper unit with automated C++ generation is indeed the best approach. That said, I’ll continue researching to see if there are any alternative technologies that might be a better fit for my situation.

                        1 Reply Last reply
                        0
                        • SavizS Saviz marked this topic as a regular topic

                        • Login

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