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

Custom class serialize with QDataStream

Scheduled Pinned Locked Moved Solved General and Desktop
6 Posts 3 Posters 7.0k 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 11 Apr 2017, 15:41 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
    • V Offline
      V Offline
      VRonin
      wrote on 11 Apr 2017, 16:00 last edited by VRonin 4 Nov 2017, 16:02
      #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 M 2 Replies Last reply 12 Apr 2017, 07:50
      3
      • V VRonin
        11 Apr 2017, 16:00

        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 12 Apr 2017, 07:50 last edited by pvt.peter 4 Dec 2017, 07:52
        #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
        • V Offline
          V Offline
          VRonin
          wrote on 12 Apr 2017, 13:28 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 13 Apr 2017, 12:29
          2
          • V VRonin
            12 Apr 2017, 13:28

            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 13 Apr 2017, 12:29 last edited by
            #5

            Hi @VRonin,

            Thanks for your reply. Your answer was the solution.

            1 Reply Last reply
            0
            • V VRonin
              11 Apr 2017, 16:00

              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;

              M Offline
              M Offline
              michalmonday
              wrote on 5 Aug 2020, 21:56 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