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. passing arguments to C++ functions
Forum Updated to NodeBB v4.3 + New Features

passing arguments to C++ functions

Scheduled Pinned Locked Moved Solved QML and Qt Quick
17 Posts 5 Posters 2.5k Views 3 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.
  • mzimmersM mzimmers

    Hi all -

    I'm not sure whether this is a QML question or a C++ question, but I figured I start here.

    I have a C++ model that uses a list of pointers to objects. These objects may be members of a parent class (Equipment) or of a subclass (eg Vsp).

    I need to perform some activities that are more appropriately performed in C++ than in QML/JS. My problem is, when I pass an argument that is a subclass, I don't know how to get my C++ function to recognize that it's a subclass. A QML call might look like:

    ColumnLayout {
        property vspStruct vsp // vspStruct is the subclass
        ...
        onButtonClicked: {
            if (equipmentModel.changesExist(vsp)) {
            ...
    

    And the C++ routine is:

    bool EquipmentModel::changesExist(Equipment e) {
    ...
    

    As you can see, this isn't going to work, because the argument is treated as a member of the parent class, but I need to look at properties of the subclass.

    So...is there something that can be done on the QML side where I can pass this a pointer or a reference or something that would allow me to cast it in the C++ function?

    Any other ideas are equally welcome. Thanks...

    Christian EhrlicherC Offline
    Christian EhrlicherC Offline
    Christian Ehrlicher
    Lifetime Qt Champion
    wrote on last edited by
    #8

    @mzimmers said in passing arguments to C++ functions:

    bool EquipmentModel::changesExist(Equipment e) {

    This is creating a copy by calling the Equipment copy ctor so no chance to do any cast to vspStruct.
    Pass it by const ref or pointer - everything else will not work.

    Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
    Visit the Qt Academy at https://academy.qt.io/catalog

    JonBJ 2 Replies Last reply
    2
    • Christian EhrlicherC Christian Ehrlicher

      @mzimmers said in passing arguments to C++ functions:

      bool EquipmentModel::changesExist(Equipment e) {

      This is creating a copy by calling the Equipment copy ctor so no chance to do any cast to vspStruct.
      Pass it by const ref or pointer - everything else will not work.

      JonBJ Offline
      JonBJ Offline
      JonB
      wrote on last edited by
      #9

      @Christian-Ehrlicher I have appended a new paragraph to my earlier response as a result of this conversation with you.

      mzimmersM 1 Reply Last reply
      0
      • JonBJ JonB

        @Christian-Ehrlicher I have appended a new paragraph to my earlier response as a result of this conversation with you.

        mzimmersM Offline
        mzimmersM Offline
        mzimmers
        wrote on last edited by
        #10

        @JonB thanks for the in-depth response. I've actually tried the virtual method approach you suggest, but I must be doing something wrong:

        // equipment.h
            virtual QVariant data(int role);
        // vsp.h
            QVariant data(int role) override;
        // equipmentModel.cpp
        bool EquipmentModel::changesExist(Equipment e) {
            e.data(256); // calls the method in equipment.h, not vsp.h.
            ...
        

        BTW: my equipment struct isn't abstract; I actually use it for some items. I'm not sure whether this makes a difference.)

        JonBJ 1 Reply Last reply
        0
        • mzimmersM mzimmers

          @JonB thanks for the in-depth response. I've actually tried the virtual method approach you suggest, but I must be doing something wrong:

          // equipment.h
              virtual QVariant data(int role);
          // vsp.h
              QVariant data(int role) override;
          // equipmentModel.cpp
          bool EquipmentModel::changesExist(Equipment e) {
              e.data(256); // calls the method in equipment.h, not vsp.h.
              ...
          

          BTW: my equipment struct isn't abstract; I actually use it for some items. I'm not sure whether this makes a difference.)

          JonBJ Offline
          JonBJ Offline
          JonB
          wrote on last edited by JonB
          #11

          @mzimmers
          Please re-read the discussion. The point is that if you have a formal parameter Equipment e this has to be passed in as a copy by value to a temporary of base-type Equipment. You pass a vspStruct as your parameter, but that does not get through to the function, it gets just an Equipment copy. And so e.data() is Equipment::data(), the vspStruct original has got lost.

          This would not happen if your method were either of

          bool EquipmentModel::changesExist([const] Equipment *e)    // pointer
          bool EquipmentModel::changesExist([const] Equipment &e)    // reference
          

          Then it would pass and receive your original vspStruct. You need to change over to one of these, not Equipment e. I believe @Axel-Spoerl & @Christian-Ehrlicher have said QML does not prevent you from doing so.

          M 1 Reply Last reply
          0
          • JonBJ JonB

            @mzimmers
            Please re-read the discussion. The point is that if you have a formal parameter Equipment e this has to be passed in as a copy by value to a temporary of base-type Equipment. You pass a vspStruct as your parameter, but that does not get through to the function, it gets just an Equipment copy. And so e.data() is Equipment::data(), the vspStruct original has got lost.

            This would not happen if your method were either of

            bool EquipmentModel::changesExist([const] Equipment *e)    // pointer
            bool EquipmentModel::changesExist([const] Equipment &e)    // reference
            

            Then it would pass and receive your original vspStruct. You need to change over to one of these, not Equipment e. I believe @Axel-Spoerl & @Christian-Ehrlicher have said QML does not prevent you from doing so.

            M Offline
            M Offline
            mpergand
            wrote on last edited by
            #12

            @JonB
            I confirm, i 've just made a test, it doesn't work with a copy passed by value.

            1 Reply Last reply
            0
            • Christian EhrlicherC Christian Ehrlicher

              @mzimmers said in passing arguments to C++ functions:

              bool EquipmentModel::changesExist(Equipment e) {

              This is creating a copy by calling the Equipment copy ctor so no chance to do any cast to vspStruct.
              Pass it by const ref or pointer - everything else will not work.

              JonBJ Offline
              JonBJ Offline
              JonB
              wrote on last edited by
              #13

              @Christian-Ehrlicher said in passing arguments to C++ functions:

              This is creating a copy by calling the Equipment copy ctor so no chance to do any cast to vspStruct.
              Pass it by const ref or pointer - everything else will not work.

              1 Reply Last reply
              0
              • mzimmersM Offline
                mzimmersM Offline
                mzimmers
                wrote on last edited by mzimmers
                #14

                @JonB said in passing arguments to C++ functions:

                You need to change over to one of these, not Equipment e. I believe @Axel-Spoerl & @Christian-Ehrlicher have said QML does not prevent you from doing so.

                Well, I tried that, and this is the result:
                Screenshot 2023-12-09 074400.png
                Notice that e is still an Equipment. By contrast, listEntry is a (pointer to a) Vsp.

                Or, am I still not understanding you?

                mzimmersM 1 Reply Last reply
                0
                • mzimmersM mzimmers

                  @JonB said in passing arguments to C++ functions:

                  You need to change over to one of these, not Equipment e. I believe @Axel-Spoerl & @Christian-Ehrlicher have said QML does not prevent you from doing so.

                  Well, I tried that, and this is the result:
                  Screenshot 2023-12-09 074400.png
                  Notice that e is still an Equipment. By contrast, listEntry is a (pointer to a) Vsp.

                  Or, am I still not understanding you?

                  mzimmersM Offline
                  mzimmersM Offline
                  mzimmers
                  wrote on last edited by
                  #15

                  So, after a little trial and error, here's where I stand:

                  1. according to @Axel-Spoerl, since my Equipment class isn't derived from QObject, QML is limited to passing it as a const reference to C++ functions.
                  2. There are (at least) 3 options for coding my C++ function:
                  • bool EquipmentModel::changesExist(Equipment e)
                  • bool EquipmentModel::changesExist(const Equipment *e)
                  • bool EquipmentModel::changesExist(const Equipment &e)
                    As @Christian-Ehrlicher pointed out, the first option won't work for me. The second option produces a run time error about incompatible JS arguments. The last option builds and runs, but the behavior is somewhat baffling:
                    Screenshot 2023-12-11 070800.png
                    My cast doesn't seem to have had the desired effect of "recapturing" the subclass. Perhaps I'm doing something wrong with this?
                  1. Interestingly enough, if I do a direct JS comparison in my QML instead of calling this routine, it works. So, if my assumptions are correct, it's really the QML-to-C++ interface that is the limitation here, and this is probably due to the fact that I'm trying to use a non-QObject based struct.

                  Unless someone has any QML-based ideas on this, I'm going to consider the matter closed. I do have more questions, but they're more appropriate for the C++ forum.

                  Thanks to everyone who helped with this.

                  JonBJ 1 Reply Last reply
                  0
                  • mzimmersM mzimmers

                    So, after a little trial and error, here's where I stand:

                    1. according to @Axel-Spoerl, since my Equipment class isn't derived from QObject, QML is limited to passing it as a const reference to C++ functions.
                    2. There are (at least) 3 options for coding my C++ function:
                    • bool EquipmentModel::changesExist(Equipment e)
                    • bool EquipmentModel::changesExist(const Equipment *e)
                    • bool EquipmentModel::changesExist(const Equipment &e)
                      As @Christian-Ehrlicher pointed out, the first option won't work for me. The second option produces a run time error about incompatible JS arguments. The last option builds and runs, but the behavior is somewhat baffling:
                      Screenshot 2023-12-11 070800.png
                      My cast doesn't seem to have had the desired effect of "recapturing" the subclass. Perhaps I'm doing something wrong with this?
                    1. Interestingly enough, if I do a direct JS comparison in my QML instead of calling this routine, it works. So, if my assumptions are correct, it's really the QML-to-C++ interface that is the limitation here, and this is probably due to the fact that I'm trying to use a non-QObject based struct.

                    Unless someone has any QML-based ideas on this, I'm going to consider the matter closed. I do have more questions, but they're more appropriate for the C++ forum.

                    Thanks to everyone who helped with this.

                    JonBJ Offline
                    JonBJ Offline
                    JonB
                    wrote on last edited by
                    #16

                    @mzimmers said in passing arguments to C++ functions:

                    bool EquipmentModel::changesExist(const Equipment &e)

                    That is the only correct one of the three.

                    If you want you can discuss elsewhere whether/how to achieve what you want.

                    mzimmersM 1 Reply Last reply
                    1
                    • JonBJ JonB

                      @mzimmers said in passing arguments to C++ functions:

                      bool EquipmentModel::changesExist(const Equipment &e)

                      That is the only correct one of the three.

                      If you want you can discuss elsewhere whether/how to achieve what you want.

                      mzimmersM Offline
                      mzimmersM Offline
                      mzimmers
                      wrote on last edited by
                      #17

                      @JonB if I understood @Axel-Spoerl correctly, the pointer version would work if I derived my struct from QQuickItem, but that's not a desired option at this time.

                      And yes, I think it's time to move this discussion to the C++ forum. Thanks again for the help.

                      1 Reply Last reply
                      0
                      • mzimmersM mzimmers has marked this topic as solved on

                      • Login

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