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

Failing qobject_cast

Scheduled Pinned Locked Moved General and Desktop
33 Posts 6 Posters 24.1k 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.
  • 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
                  • T Offline
                    T Offline
                    tallia1
                    wrote on last edited by
                    #23

                    Let me use a small diagram to describe what is happening:
                    "Diagram":https://docs.google.com/drawings/d/1Jp-wpPuFTCvsC-3ovRmZXlRj93U0TfS7urxpfkLZPEc/edit

                    The core runtime loads the plugins1/2

                    Everything else is statically linked to Core Runtime

                    Core runtime calls plugin1 to generate an instance of SurfaceMeshModel

                    (note: plugin1 casts this instance to the more general Model which is the only thing runtime knows about as the diagram shows)

                    Core runtime calls plugin2, which receives Model* and needs to cast it back down to SurfaceMeshModel <=== This is the failure point

                    What I mentioned above is that now the cast/uncast of an object within a single plugin works well. But if I create an object and pass it to another plugin... that's where the casting fails...

                    Do you see any fault with my design?

                    Andrea

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

                      Your SurfaceMeshModel must be defined ONLY once in your application. If Plugin1 and Plugin2 need to know and use SurfaceMeshModel and even more pass instances of it, then you need an extra shared library that will offer it to the plugins. You must then link both your plugins to that library.
                      If you compile the SurfaceMeshModel in each plugin, it will work locally in that plugin but not outside of the plugin boundaries using qobject_cast.
                      The reason is that each plugin will have its own QMetaObject (because of the MOCed Q_OBJECT macro) for that SurfaceMeshModel class. And from a Qt standpoint two classes with different QMetaObject instances are not the same class, even if they have the exact same interface and all.
                      However, I am sure it would work flawlessly with a static_cast as the compiler has generated the same code and memory layout in both plugins but this is not a good practice in general.
                      You need an extra shared library (that your Core runtime does not need to know as far as it is concerned).

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

                        Hey rcari, fact is.. I did create an extra shared library doing exactly what you say!
                        I am building some example code to show you guys. But as you say, within both plugins I have a "pri" file that loads the SurfaceMeshModel class:

                        @
                        macx:POST_TARGETDEPS += $$SOURCE_ROOT/libraries/lib_surfacemesh.a
                        macx:LIBS += -L$$SOURCE_ROOT/libraries -l_surfacemesh
                        @

                        And yes, the core library is unaware of this shared (static) library used by both plugins.
                        Let me see if the static_cast will work, just for the heck of it :)

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

                          You can't use it as a static lib, it breaks the whole point. The static lib will be fully included in each plugin.
                          You need a SHARED library (in opposite to STATIC, not as a conceptual shared compilation unit).
                          Using a SHARED library, when one of the plugins requiring it is loaded, this extra library is loaded as well, when the second plugin is loaded, the extra library is already loaded and they SHARE that code.
                          See http://en.wikipedia.org/wiki/Library_(computing)

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

                            Here you go :) Rcari I think you solved the problem. What you are saying makes perfect sense!

                            Indeed, static_cast did work (pointer was not null), but when I then tried to use the casted object I got some wacky runtime error!!

                            I will let you know if changing to dynamic library will solve it. Thank you so much for your input :)

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

                              LaCie? I think I have a usb key in the shape of a real key from your company :)

                              1 Reply Last reply
                              0
                              • A Offline
                                A Offline
                                andre
                                wrote on last edited by
                                #29

                                @
                                class LOCSurfaceMeshModel : public Model, public Surface_mesh{
                                Q_OBJECT
                                Q_INTERFACES(Model)
                                public:
                                LOCSurfaceMeshModel(){}
                                };
                                @
                                Seems a bit weird. I think the Q_INTERFACES(Model) declaration is wrong (and just unneeded).

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

                                  Actually I already run into this before :)
                                  It is needed, basically you can only qobject_cast to what you have declared as being a Q_INTERFACES. Anything else will fail :)

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

                                    Well, that is highly probable :)
                                    [quote author="tallia1" date="1319872616"]LaCie? I think I have a usb key in the shape of a real key from your company :)[/quote]

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

                                      [quote author="tallia1" date="1319874092"]Actually I already run into this before :)
                                      It is needed, basically you can only qobject_cast to what you have declared as being a Q_INTERFACES. Anything else will fail :)[/quote]

                                      Well that is true for non QObject classes. For QObject you can safely go up the inheritance tree using qobject_cast without declaring interfaces. I agree that this interface thing seems unneeded. However because of your architecture, I don't know for sure if that is still true across plugins boundaries...

                                      1 Reply Last reply
                                      0
                                      • A Offline
                                        A Offline
                                        andre
                                        wrote on last edited by
                                        #33

                                        [quote author="tallia1" date="1319874092"]Actually I already run into this before :)
                                        It is needed, basically you can only qobject_cast to what you have declared as being a Q_INTERFACES. Anything else will fail :)[/quote]

                                        That is only true for non-QObjects, AFAIK. As your model is already a QObject, there is no need for it.

                                        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