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. QMetaType casting to desired type
Forum Updated to NodeBB v4.3 + New Features

QMetaType casting to desired type

Scheduled Pinned Locked Moved Unsolved General and Desktop
11 Posts 3 Posters 2.4k Views 2 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.
  • R Offline
    R Offline
    Redman
    wrote on last edited by
    #1

    Hello,

    I want to cast an object I receive over network to the specific class that represents that objects structure. The receiver object, before casting, is a generic networking class. I want to achieve that using QMetaType.

    Right now I have something like this

          // Check for cast compatibility
          QString className = "ExampleClass"
          QMetaType targetType = QMetaType::fromName(className.toUtf8());
          QMetaType sourceTarget = QMetaType::fromType<NetworkClass>();
          bool canConvert = QMetaType::canConvert(sourceTarget , targetType);
          if (!type.isValid() || !canConvert) {
             qWarning() << "targetType not valid or can not convert to targetType";
             break;
          }
    
    # untill here all works fine
    
    ???
    

    What to do after that. I tried a lot of things. All QMetaType functions return void* which I cant do nothing with.

    I could write down every possible qobject_cast in a switch statement but I want to keep this as dynamic as possible

    A 1 Reply Last reply
    0
    • jeremy_kJ Offline
      jeremy_kJ Offline
      jeremy_k
      wrote on last edited by
      #2

      How is the object transmitted? I had presumed this was for POD classes until the mention of qobject_cast.

      As far as doing something with the reconstructed object, what's the goal? Ignoring the transmission question, if the object is QObject derived, the QMetaObject::invoke* and property functions can be used.

      If the goal is a symbol referring to a derived type, perhaps a template function accepting a parameter pack of types could return a std::variant or similar and save a little typing.

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

      1 Reply Last reply
      0
      • R Redman

        Hello,

        I want to cast an object I receive over network to the specific class that represents that objects structure. The receiver object, before casting, is a generic networking class. I want to achieve that using QMetaType.

        Right now I have something like this

              // Check for cast compatibility
              QString className = "ExampleClass"
              QMetaType targetType = QMetaType::fromName(className.toUtf8());
              QMetaType sourceTarget = QMetaType::fromType<NetworkClass>();
              bool canConvert = QMetaType::canConvert(sourceTarget , targetType);
              if (!type.isValid() || !canConvert) {
                 qWarning() << "targetType not valid or can not convert to targetType";
                 break;
              }
        
        # untill here all works fine
        
        ???
        

        What to do after that. I tried a lot of things. All QMetaType functions return void* which I cant do nothing with.

        I could write down every possible qobject_cast in a switch statement but I want to keep this as dynamic as possible

        A Offline
        A Offline
        Asperamanca
        wrote on last edited by
        #3

        @Redman
        I guess you are missing this code:

        MyType myTypedValue = {};
        QMetaType::convert(sourceTarget, targetType, &myTypedValue);
        
        jeremy_kJ 1 Reply Last reply
        0
        • A Asperamanca

          @Redman
          I guess you are missing this code:

          MyType myTypedValue = {};
          QMetaType::convert(sourceTarget, targetType, &myTypedValue);
          
          jeremy_kJ Offline
          jeremy_kJ Offline
          jeremy_k
          wrote on last edited by jeremy_k
          #4

          @Asperamanca said in QMetaType casting to desired type:

          @Redman
          I guess you are missing this code:

          I saw that, and it surprised me that a sequence of bytes delivered over a network would successfully convert to a QObject.

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

          R A 2 Replies Last reply
          0
          • jeremy_kJ jeremy_k

            @Asperamanca said in QMetaType casting to desired type:

            @Redman
            I guess you are missing this code:

            I saw that, and it surprised me that a sequence of bytes delivered over a network would successfully convert to a QObject.

            R Offline
            R Offline
            Redman
            wrote on last edited by
            #5

            @jeremy_k I'm talking QtRemoteObjects. I intentionally left that piece of information out because every time I mention them in this forum my posts never get answered.

            So what exactly is happening?

            I have a class ExampleClass

            class ExampleClass : public ExampleClassSimpleSource {
               Q_OBJECT
                 .
                 .
                 .
            

            Which gets remoted via

            bool rslt = myRegistry.enableRemoting(&obj);
            

            somewhere in my code.

            Retrieving that remoted object via

                 QSharedPointer<ExampleClassReplica> rep;
                 rep.reset(node.data()->acquire<ExampleClassReplica>(id));
            

            Now, obviously I want to have more classes I can remote than this ExampleClass. But for now I have this solution.

            // Enum of my classes which are used as remote objects
                  RO ro = static_cast<T>(
                              QMetaEnum::fromType<RO>().keyToValue(entry.second.typeName.toLocal8Bit()));
                  switch (ro) {
                     case RoReceiver::ExampleClass: {
                        QSharedPointer<ExampleClassReplica> rep;
                        rep.reset(node.data()->acquire<ExampleClassReplica>(id));
            
                        // Helps us keep track of the remote objects
                        connect(rep.data(), SIGNAL(removeChanged(bool)),
                            m_instanceTest.data(), SLOT(recRemoveChanged(bool)));
                        connect(rep.data(), &QRemoteObjectReplica::initialized,
                            m_instanceTest.data(), &RoReceiverTest::recInitChanged);
            
                        // Keep track of available remote objects
                        rep.data()->setObjectName(id);
                        m_instanceTest.data()->m_nodes[node].insert(id, rep);
                        Q_EMIT m_instanceTest.data()->echoRecRemoteObjectTest(rep);
                        return;
                     } break;
                  }
            

            This switch statement is gonna get bigger and bigger aswell as be error prone.
            Is there any way to make this piece of code dynamic?

            A jeremy_kJ 2 Replies Last reply
            0
            • jeremy_kJ jeremy_k

              @Asperamanca said in QMetaType casting to desired type:

              @Redman
              I guess you are missing this code:

              I saw that, and it surprised me that a sequence of bytes delivered over a network would successfully convert to a QObject.

              A Offline
              A Offline
              Asperamanca
              wrote on last edited by
              #6

              @jeremy_k said in QMetaType casting to desired type:

              @Asperamanca said in QMetaType casting to desired type:

              @Redman
              I guess you are missing this code:

              I saw that, and it surprised me that a sequence of bytes delivered over a network would successfully convert to a QObject.

              Anything in a computer is really just a sequence of bytes (or bits). Just a matter on how you view it...

              jeremy_kJ 1 Reply Last reply
              0
              • R Redman

                @jeremy_k I'm talking QtRemoteObjects. I intentionally left that piece of information out because every time I mention them in this forum my posts never get answered.

                So what exactly is happening?

                I have a class ExampleClass

                class ExampleClass : public ExampleClassSimpleSource {
                   Q_OBJECT
                     .
                     .
                     .
                

                Which gets remoted via

                bool rslt = myRegistry.enableRemoting(&obj);
                

                somewhere in my code.

                Retrieving that remoted object via

                     QSharedPointer<ExampleClassReplica> rep;
                     rep.reset(node.data()->acquire<ExampleClassReplica>(id));
                

                Now, obviously I want to have more classes I can remote than this ExampleClass. But for now I have this solution.

                // Enum of my classes which are used as remote objects
                      RO ro = static_cast<T>(
                                  QMetaEnum::fromType<RO>().keyToValue(entry.second.typeName.toLocal8Bit()));
                      switch (ro) {
                         case RoReceiver::ExampleClass: {
                            QSharedPointer<ExampleClassReplica> rep;
                            rep.reset(node.data()->acquire<ExampleClassReplica>(id));
                
                            // Helps us keep track of the remote objects
                            connect(rep.data(), SIGNAL(removeChanged(bool)),
                                m_instanceTest.data(), SLOT(recRemoveChanged(bool)));
                            connect(rep.data(), &QRemoteObjectReplica::initialized,
                                m_instanceTest.data(), &RoReceiverTest::recInitChanged);
                
                            // Keep track of available remote objects
                            rep.data()->setObjectName(id);
                            m_instanceTest.data()->m_nodes[node].insert(id, rep);
                            Q_EMIT m_instanceTest.data()->echoRecRemoteObjectTest(rep);
                            return;
                         } break;
                      }
                

                This switch statement is gonna get bigger and bigger aswell as be error prone.
                Is there any way to make this piece of code dynamic?

                A Offline
                A Offline
                Asperamanca
                wrote on last edited by
                #7

                @Redman Looks like you should be able to at least put most of the case content into a template function, so your switch should look like

                switch(ro) {
                   case RoReceiver::ExampleClass: {
                      createRemoteObject<ExampleClassReplica>(node, id, m_instanceTest);
                      return;
                   }
                   // ...more cases
                
                R 1 Reply Last reply
                0
                • A Asperamanca

                  @Redman Looks like you should be able to at least put most of the case content into a template function, so your switch should look like

                  switch(ro) {
                     case RoReceiver::ExampleClass: {
                        createRemoteObject<ExampleClassReplica>(node, id, m_instanceTest);
                        return;
                     }
                     // ...more cases
                  
                  R Offline
                  R Offline
                  Redman
                  wrote on last edited by Redman
                  #8

                  @Asperamanca That is correct.
                  What makes me wonder is that I qRegisterMetaType<ExampleClassReplica>(); which makes it usable with QMetaType. The way I understood QMetaType is that it provides reflection functionality. By calling QMetaType::create/convert I expected to get the correct type. But all it returns is a void* which I can not cast without explicitly knowing the type during compile time

                  A 1 Reply Last reply
                  0
                  • R Redman

                    @Asperamanca That is correct.
                    What makes me wonder is that I qRegisterMetaType<ExampleClassReplica>(); which makes it usable with QMetaType. The way I understood QMetaType is that it provides reflection functionality. By calling QMetaType::create/convert I expected to get the correct type. But all it returns is a void* which I can not cast without explicitly knowing the type during compile time

                    A Offline
                    A Offline
                    Asperamanca
                    wrote on last edited by
                    #9

                    @Redman
                    I have to admit, I have never created objects in such a fashion myself.
                    But maybe the following works:

                    QVariant v;
                    QMetaType::convert(sourceTarget, targetType, v.data());
                    // Maybe also needed:
                    v.convert(targetType);
                    

                    If that works, and the contained type is a QObject type, you should be able to generically access properties, enumerations and suchlike.

                    1 Reply Last reply
                    0
                    • A Asperamanca

                      @jeremy_k said in QMetaType casting to desired type:

                      @Asperamanca said in QMetaType casting to desired type:

                      @Redman
                      I guess you are missing this code:

                      I saw that, and it surprised me that a sequence of bytes delivered over a network would successfully convert to a QObject.

                      Anything in a computer is really just a sequence of bytes (or bits). Just a matter on how you view it...

                      jeremy_kJ Offline
                      jeremy_kJ Offline
                      jeremy_k
                      wrote on last edited by
                      #10

                      @Asperamanca said in QMetaType casting to desired type:

                      @jeremy_k said in QMetaType casting to desired type:

                      @Asperamanca said in QMetaType casting to desired type:

                      @Redman
                      I guess you are missing this code:

                      I saw that, and it surprised me that a sequence of bytes delivered over a network would successfully convert to a QObject.

                      Anything in a computer is really just a sequence of bytes (or bits). Just a matter on how you view it...

                      Structure within the data that includes pointers makes treating an object as just a sequence of bytes a little more complicated.

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

                      1 Reply Last reply
                      0
                      • R Redman

                        @jeremy_k I'm talking QtRemoteObjects. I intentionally left that piece of information out because every time I mention them in this forum my posts never get answered.

                        So what exactly is happening?

                        I have a class ExampleClass

                        class ExampleClass : public ExampleClassSimpleSource {
                           Q_OBJECT
                             .
                             .
                             .
                        

                        Which gets remoted via

                        bool rslt = myRegistry.enableRemoting(&obj);
                        

                        somewhere in my code.

                        Retrieving that remoted object via

                             QSharedPointer<ExampleClassReplica> rep;
                             rep.reset(node.data()->acquire<ExampleClassReplica>(id));
                        

                        Now, obviously I want to have more classes I can remote than this ExampleClass. But for now I have this solution.

                        // Enum of my classes which are used as remote objects
                              RO ro = static_cast<T>(
                                          QMetaEnum::fromType<RO>().keyToValue(entry.second.typeName.toLocal8Bit()));
                              switch (ro) {
                                 case RoReceiver::ExampleClass: {
                                    QSharedPointer<ExampleClassReplica> rep;
                                    rep.reset(node.data()->acquire<ExampleClassReplica>(id));
                        
                                    // Helps us keep track of the remote objects
                                    connect(rep.data(), SIGNAL(removeChanged(bool)),
                                        m_instanceTest.data(), SLOT(recRemoveChanged(bool)));
                                    connect(rep.data(), &QRemoteObjectReplica::initialized,
                                        m_instanceTest.data(), &RoReceiverTest::recInitChanged);
                        
                                    // Keep track of available remote objects
                                    rep.data()->setObjectName(id);
                                    m_instanceTest.data()->m_nodes[node].insert(id, rep);
                                    Q_EMIT m_instanceTest.data()->echoRecRemoteObjectTest(rep);
                                    return;
                                 } break;
                              }
                        

                        This switch statement is gonna get bigger and bigger aswell as be error prone.
                        Is there any way to make this piece of code dynamic?

                        jeremy_kJ Offline
                        jeremy_kJ Offline
                        jeremy_k
                        wrote on last edited by
                        #11

                        @Redman said in QMetaType casting to desired type:

                        @jeremy_k I'm talking QtRemoteObjects. I intentionally left that piece of information out because every time I mention them in this forum my posts never get answered.

                        That's an important detail. It sounds like a useful project. I personally have remained minimally interested due to the project's stated lack of interest in compatibility with non-QRO implementations. I'm not lucky enough to work in a distributed environment where all nodes run a compatible Qt application.

                        This switch statement is gonna get bigger and bigger aswell as be error prone.
                        Is there any way to make this piece of code dynamic?

                        I was imagining:

                        template <class Type, class... Others> std::any convert(void *obj) {
                            QMetaType fromType = QMetaType::fromType<NetworkClass>();
                            QMetaType toType = QMetaType::fromType<Type>();
                            std::any ret;
                            if QMetaType::canConvert(fromType, toType) {
                                QMetaType::convert(obj, fromType, &ret, toType);
                                return ret;
                            }
                            else
                                return convert<Others...>(obj);
                        }
                        
                        template <> convert(void *obj) {
                            return std::any(nullptr);
                        }
                        
                        NetworkClass *obj = getObject();
                        std::any convertedObject = convert<Type1, Type2, Type3>(obj);
                        if (std::any_cast<void *>(convertedObject) != nullptr)
                            ...
                        
                        1. Not expected to compile as is
                        2. Not runtime dynamic
                        3. The user of the std::any will need to know what it wants to convert it to

                        I'm not sure this improves the situation.

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

                        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