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. Custom class serialize with QDataStream

Custom class serialize with QDataStream

Scheduled Pinned Locked Moved Solved General and Desktop
6 Posts 3 Posters 6.9k Views
  • 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.
  • P Offline
    P Offline
    pvt.peter
    wrote on last edited by
    #1

    Hi Everybody,

    I have got a TreeItem custom class (not derived from QObject) which is "wrapped" into QVariant and i would like to serialize and deserialize it with QDataStream.
    TreeItem represents a multi-level Tree with a list of child pointers and a parent pointer.
    I placed the implemented operator<< and operator>> methods before main() method and qRegisterMetaTypeStreamOperators<TreeItem>("TreeItem"); in the first line of main() method.
    I have defined a Q_DECLARE_METATYPE(TreeItem*) macro too.

    See above:

    #include "TheApp.h"
    #include <QtWidgets/QApplication>
    #include "TreeItem.h"
    
    QDataStream &operator<<(QDataStream &out, const TreeItem &rhs) {
       out.writeRawData(reinterpret_cast<const char*>(&rhs), sizeof(rhs));
       return out;
    }
    
    QDataStream &operator>>(QDataStream &in, TreeItem &rhs) {
       in.readRawData(reinterpret_cast<char*>(&rhs), sizeof(rhs));
       return in;
    }
    
    int main(int argc, char *argv[])
    {
       QApplication a(argc, argv);
       qRegisterMetaTypeStreamOperators<TreeItem>("TreeItem");
       QCoreApplication::setApplicationName(QString("TheApp"));
       TheApp w;
       w.show();
       return a.exec();
    }
    

    I would like to encode it with the following:

    QByteArray encodedData;
    QDataStream stream(&encodedData, QIODevice::WriteOnly);
    TreeItem* treeItem = new TreeItem();
    QVariant treeItemQVariant = QVariant::fromValue(treeItem);
    stream << treeItemQVariant;
    

    When i execute "stream << treeItemQVariant;" i got this error message:

       QVariant::save: unable to save type 'TreeItem*' (type id: 1037).
       ASSERT failure in QVariant::save: "Invalid type to save", file kernel\qvariant.cpp, line 2144
       Debug Error!
    

    What is the problem?
    How can i (de)serialize a custom class with QDataStream which is "wrapped" into a QVariant?

    Thanks in advance,
    It should be a big help for me,
    BR,
    Peter

    1 Reply Last reply
    0
    • VRoninV Offline
      VRoninV Offline
      VRonin
      wrote on last edited by VRonin
      #2

      I don't like your serialisation with reinterpret_cast but the main point here is that you are getting confused by the pointer.

      change Q_DECLARE_METATYPE(TreeItem*) to Q_DECLARE_METATYPE(TreeItem)
      and change QVariant treeItemQVariant = QVariant::fromValue(treeItem); to QVariant treeItemQVariant = QVariant::fromValue(*treeItem); (be carefull not to leak treeItem)

      @pvt.peter said in Custom class serialize with QDataStream:

      How can i (de)serialize a custom class with QDataStream which is "wrapped" into a QVariant?

      QVariant TempVariant;
      stream >> TempVariant;
      *treeItem = TempVariant.value<TreeItem>();
      

      P.S.
      in your code snippet you don't really need to pass through QVariant btw, you can just use stream << *treeItem;

      "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
      ~Napoleon Bonaparte

      On a crusade to banish setIndexWidget() from the holy land of Qt

      P michalmondayM 2 Replies Last reply
      3
      • VRoninV VRonin

        I don't like your serialisation with reinterpret_cast but the main point here is that you are getting confused by the pointer.

        change Q_DECLARE_METATYPE(TreeItem*) to Q_DECLARE_METATYPE(TreeItem)
        and change QVariant treeItemQVariant = QVariant::fromValue(treeItem); to QVariant treeItemQVariant = QVariant::fromValue(*treeItem); (be carefull not to leak treeItem)

        @pvt.peter said in Custom class serialize with QDataStream:

        How can i (de)serialize a custom class with QDataStream which is "wrapped" into a QVariant?

        QVariant TempVariant;
        stream >> TempVariant;
        *treeItem = TempVariant.value<TreeItem>();
        

        P.S.
        in your code snippet you don't really need to pass through QVariant btw, you can just use stream << *treeItem;

        P Offline
        P Offline
        pvt.peter
        wrote on last edited by pvt.peter
        #3

        @VRonin Thanks for your reply, i did your modifications and it works with QVariant.

        But how can i use stream << *treeItem; ?
        Now i use the following codes:

        Q_DECLARE_METATYPE(TreeItem)
        

        QDataStream &operator<<(QDataStream &out, const TreeItem& rhs) {
           out.writeRawData(reinterpret_cast<const char*>(&rhs), sizeof(rhs));
           return out;
        }
        QDataStream &operator>>(QDataStream &in, TreeItem &rhs) {
           in.readRawData(reinterpret_cast<char*>(&rhs), sizeof(rhs));
           return in;
        }
        

        qRegisterMetaTypeStreamOperators<TreeItem>("TreeItem");
        

        TreeItem* treeItem = new TreeItem();
        stream << *treeItem;
        

        TreeItem* data2 = nullptr;
        while (!stream.atEnd()) {
           stream >> *data2;
        }
        

        There are some trouble with operator << and operator >>.
        No 'operator <<' matches arguments of type 'QDataStream' and 'TreeItem'
        No 'operator >>' matches arguments of type 'QDataStream' and 'TreeItem'
        How can i fix them?

        1 Reply Last reply
        0
        • VRoninV Offline
          VRoninV Offline
          VRonin
          wrote on last edited by
          #4

          You just have to declare the prototype QDataStream &operator<<(QDataStream &, const TreeItem& ) in the header file of TreeItem

          "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
          ~Napoleon Bonaparte

          On a crusade to banish setIndexWidget() from the holy land of Qt

          P 1 Reply Last reply
          2
          • VRoninV VRonin

            You just have to declare the prototype QDataStream &operator<<(QDataStream &, const TreeItem& ) in the header file of TreeItem

            P Offline
            P Offline
            pvt.peter
            wrote on last edited by
            #5

            Hi @VRonin,

            Thanks for your reply. Your answer was the solution.

            1 Reply Last reply
            0
            • VRoninV VRonin

              I don't like your serialisation with reinterpret_cast but the main point here is that you are getting confused by the pointer.

              change Q_DECLARE_METATYPE(TreeItem*) to Q_DECLARE_METATYPE(TreeItem)
              and change QVariant treeItemQVariant = QVariant::fromValue(treeItem); to QVariant treeItemQVariant = QVariant::fromValue(*treeItem); (be carefull not to leak treeItem)

              @pvt.peter said in Custom class serialize with QDataStream:

              How can i (de)serialize a custom class with QDataStream which is "wrapped" into a QVariant?

              QVariant TempVariant;
              stream >> TempVariant;
              *treeItem = TempVariant.value<TreeItem>();
              

              P.S.
              in your code snippet you don't really need to pass through QVariant btw, you can just use stream << *treeItem;

              michalmondayM Offline
              michalmondayM Offline
              michalmonday
              wrote on last edited by
              #6

              @VRonin said in Custom class serialize with QDataStream:

              I don't like your serialisation with reinterpret_cast

              What is wrong with it? Is there any real risk associatied with using it in such situation? Or is it just a prejuidice because it is generally regarded to be unsafe?

              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