Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Failing qobject_cast
Forum Updated to NodeBB v4.3 + New Features

Failing qobject_cast

Scheduled Pinned Locked Moved General and Desktop
33 Posts 6 Posters 23.6k 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.
  • F Offline
    F Offline
    Franzk
    wrote on last edited by
    #3

    [quote author="rcari" date="1319722285"]I know this is a weird question but are you sure your model is not NULL in the first place ?[/quote]

    This is actually a good question.

    [quote]Plus, why do you use qobject_cast here, when a static_cast would be much more efficient ?[/quote]qobject_cast() simply is safer. If this particular cast turns out to be a performance hog, then it is time to start thinking about static_cast()ing. Remember that premature optimization is the root of all evil, and that more programming sins are committed in the name of performance than any other, including blind stupidity.

    "Horse sense is the thing a horse has which keeps it from betting on people." -- W.C. Fields

    http://www.catb.org/~esr/faqs/smart-questions.html

    1 Reply Last reply
    0
    • P Offline
      P Offline
      p-himik
      wrote on last edited by
      #4

      [quote author="Franzk" date="1319726749"]
      [quote author="rcari" date="1319722285"]I know this is a weird question but are you sure your model is not NULL in the first place ?[/quote]

      This is actually a good question.
      [/quote]

      I don't think so since tallia1 calls model->metaObject(). If model == 0 the app would crash at this point, not later.

      1 Reply Last reply
      0
      • R Offline
        R Offline
        rcari
        wrote on last edited by
        #5

        That was my point however, some compiler magic could lead to cases where it wouldn't even lookup the vtable to place the call for metaObject(), thus not requiring to dereference the pointer... I agree that would be serious trickery...

        1 Reply Last reply
        0
        • F Offline
          F Offline
          Franzk
          wrote on last edited by
          #6

          Hmm, well spotted. I think you need to dig into the qobject_cast to see what's going wrong.

          "Horse sense is the thing a horse has which keeps it from betting on people." -- W.C. Fields

          http://www.catb.org/~esr/faqs/smart-questions.html

          1 Reply Last reply
          0
          • G Offline
            G Offline
            goetz
            wrote on last edited by
            #7

            Is the Surface_mesh class based on QObject too?

            And what is the output of this snippet:

            @
            const QMetaObject *mo = model->metaObject();
            while(mo) {
            qDebug() << mo->className();
            mo = mo->superClass();
            }
            @

            http://www.catb.org/~esr/faqs/smart-questions.html

            1 Reply Last reply
            0
            • T Offline
              T Offline
              tallia1
              wrote on last edited by
              #8

              I just spent my morning trying to figure it out. Indeed rcari
              is right, I didn't need to to qobject_cast. I was using it mostly
              because I wanted to use introspection to see whether I was
              doing something wrong...

              An important note is that the two classes are located in
              different dynamically loaded libraries... so I am not sure
              I can use the C++ dynamic_cast there...

              I will try what you suggest Volker.

              1 Reply Last reply
              0
              • G Offline
                G Offline
                goetz
                wrote on last edited by
                #9

                qobject_cast should be safe over DLL boundaries - that's at least what the docs state. You did not answer whether the Surface_mesh class is based on QObject too?

                http://www.catb.org/~esr/faqs/smart-questions.html

                1 Reply Last reply
                0
                • T Offline
                  T Offline
                  tallia1
                  wrote on last edited by
                  #10

                  Hi Volker,

                  Indeed, that's why I was using qobject_cast at a certain point (and going back to it right now)

                  And to answer your question, yes it is:
                  @
                  class SurfaceMeshModel : public Model, public Surface_mesh{
                  Q_OBJECT
                  Q_INTERFACES(Model)
                  ...
                  @

                  1 Reply Last reply
                  0
                  • G Offline
                    G Offline
                    goetz
                    wrote on last edited by
                    #11

                    That was clear, SurfaceMeshModel inherits Model which eventually inherits QObject.

                    The question is, does your second base class, Surface_mesh, inherit QObject too (directly or indirectly) - i.e. what's the class hierarchy for the Surface_mesh class?

                    http://www.catb.org/~esr/faqs/smart-questions.html

                    1 Reply Last reply
                    0
                    • T Offline
                      T Offline
                      tallia1
                      wrote on last edited by
                      #12

                      Oh sorry, misunderstood your question. Surface_mesh is an external library and not Qt, so no, it doesn't know anything about Qt at all..

                      1 Reply Last reply
                      0
                      • G Offline
                        G Offline
                        goetz
                        wrote on last edited by
                        #13

                        Ok. That's good. It's not allowed to inherit QObject via two different paths.

                        So, what's the output of that little debug loop I pasted earlier?

                        http://www.catb.org/~esr/faqs/smart-questions.html

                        1 Reply Last reply
                        0
                        • T Offline
                          T Offline
                          tallia1
                          wrote on last edited by
                          #14

                          And this is the output of this snippet:

                          @
                          const QMetaObject *mo = model->metaObject();
                          qDebug() << "Hierarchy: ";
                          while(mo) {
                          qDebug() << " " << mo->className();
                          mo = mo->superClass();
                          }
                          @

                          Output:
                          @
                          Hierarchy:
                          SurfaceMeshModel
                          Model
                          QObject
                          MASSIVE FAIL.. TERMINATING
                          @

                          1 Reply Last reply
                          0
                          • G Offline
                            G Offline
                            goetz
                            wrote on last edited by
                            #15

                            This is really strange. Can you boil down the code to small, yet complete test case that demonstrates the error? I don't have any clue, whats going wrong here. BTW: what operating system are you on?

                            http://www.catb.org/~esr/faqs/smart-questions.html

                            1 Reply Last reply
                            0
                            • T Offline
                              T Offline
                              tallia1
                              wrote on last edited by
                              #16

                              I am on OSX Lion. I isolated the problem even more. Look at the snippet below:

                              @
                              SurfaceMeshModel* model = new SurfaceMeshModel(path);

                              Model* retval = qobject_cast<Model*>(model);
                              qDebug() << "Conversion Mesh=>Model: " << (retval?"success":"failed");

                              SurfaceMeshModel* mesh = qobject_cast<SurfaceMeshModel*>(retval);
                              qDebug() << "Conversion Model=>Mesh: " << (mesh?"success":"failed");
                              @

                              And the output is ...
                              @
                              Conversion Mesh=>Model: success
                              Conversion Model=>Mesh: failed
                              @

                              1 Reply Last reply
                              0
                              • T Offline
                                T Offline
                                tallia1
                                wrote on last edited by
                                #17

                                And now I just replaced the qobject_cast with a dynamic cast. I get a "success, success" in the test above, but a fail when it goes across the DLL boundaries (the snipped above was within the boundaries of a single compiled element).

                                1 Reply Last reply
                                0
                                • G Offline
                                  G Offline
                                  goetz
                                  wrote on last edited by
                                  #18

                                  Just for curiosity, what's the output of

                                  @
                                  qDebug() << "model :" << model;
                                  qDebug() << "retval:" << retval;
                                  qDebug() << "mesh :" << mesh;
                                  @

                                  http://www.catb.org/~esr/faqs/smart-questions.html

                                  1 Reply Last reply
                                  0
                                  • T Offline
                                    T Offline
                                    tallia1
                                    wrote on last edited by
                                    #19

                                    By using both qobject_cast:

                                    @
                                    Conversion Mesh=>Model: success
                                    Conversion Model=>Mesh: failed
                                    model : SurfaceMeshModel(0x1023b3fc0)
                                    retval: SurfaceMeshModel(0x1023b3fc0)
                                    mesh : QObject(0x0)
                                    @

                                    1 Reply Last reply
                                    0
                                    • G Offline
                                      G Offline
                                      goetz
                                      wrote on last edited by
                                      #20

                                      Weird. It's completely weird.

                                      Just a another blind guess: may it be, that you happen to load two different versions of the Qt libs via the two libraries (resp. your app and library)? This may cause trouble too.

                                      You can check this with the otool tool on the mac and some dyld debug settings:

                                      @
                                      export DYLD_PRINT_LIBRARIES=1
                                      /path/to/your/Program.app/Contents/MacOS/Program 2>LOG-libraries.txt
                                      unset DYLD_PRINT_LIBRARIES
                                      @

                                      Then check LOG-libraries.txt for the loaded Qt libraries:

                                      @
                                      grep Qt LOG-libraries.txt
                                      @

                                      It must not print libraries from different paths.

                                      http://www.catb.org/~esr/faqs/smart-questions.html

                                      1 Reply Last reply
                                      0
                                      • T Offline
                                        T Offline
                                        tallia1
                                        wrote on last edited by
                                        #21

                                        I think I am approaching the esoteric here :)

                                        These two are defined in the same header that will compile into
                                        the same library:
                                        @
                                        class LOCSurfaceMeshModel : public Model, public Surface_mesh{
                                        Q_OBJECT
                                        Q_INTERFACES(Model)
                                        public:
                                        LOCSurfaceMeshModel(){}
                                        };

                                        class SurfaceMeshModel : public Model, public Surface_mesh{
                                        Q_OBJECT
                                        Q_INTERFACES(Model)
                                        ....
                                        };
                                        @

                                        Then this block is executed:

                                        @
                                        {
                                        LOCSurfaceMeshModel* mod = new LOCSurfaceMeshModel();
                                        Model* retval = qobject_cast<Model*>(mod);
                                        qDebug() << "Conversion Mesh=>Model: " << (retval?"success":"failed");
                                        LOCSurfaceMeshModel* mesh = qobject_cast<LOCSurfaceMeshModel*>(retval);
                                        qDebug() << "Conversion Model=>Mesh: " << (mesh?"success":"failed");
                                        }
                                        {
                                        SurfaceMeshModel* mod = new SurfaceMeshModel();
                                        Model* retval = qobject_cast<Model*>(mod);
                                        qDebug() << "Conversion Mesh=>Model: " << (retval?"success":"failed");
                                        SurfaceMeshModel* mesh = qobject_cast<SurfaceMeshModel*>(retval);
                                        qDebug() << "Conversion Model=>Mesh: " << (mesh?"success":"failed");
                                        }
                                        @

                                        And "OBVIOUSLY" the output is...
                                        @
                                        Conversion Mesh=>Model: success
                                        Conversion Model=>Mesh: success
                                        Conversion Mesh=>Model: success
                                        Conversion Model=>Mesh: failed
                                        @

                                        Complete NO-SENSE... Sigh.. I will go by elimination now..
                                        I will strip down the original class to the one that work..

                                        1 Reply Last reply
                                        0
                                        • T Offline
                                          T Offline
                                          tallia1
                                          wrote on last edited by
                                          #22

                                          So by following the process above I found my error. It was this stray include lying in my runtime subsystem. (there was a time where I turned off the plugin system and did things locally)

                                          @
                                          #include "../lib_surfacemesh/SurfaceMeshModel.h" /// TO BE REMOVED
                                          @

                                          I wish I could offer more intuition on WHY it was causing the whole dynamic casting to fail.. But I seriously have no clue!

                                          NOTE: this fixed the cast/uncast ONLY when I was trying my test code. If an object is created from a plugin, casted to the interface object and casted back to the subclass in a second plugin... the cast still fails... triple sigh...

                                          1 Reply Last reply
                                          0

                                          • Login

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