Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-32227

Unmarshalling of complex types in DBus 'v' variants not working

    XMLWordPrintable

Details

    • Bug
    • Resolution: Invalid
    • Not Evaluated
    • None
    • 5.0.0
    • D-Bus
    • None
    • Both x86 and ARM Qt5.0

    Description

      It seems the unmarshalling of a complex type (e.g. struct) from a QDBusVariant (dbus datatype 'v') is not working properly.

      Some sample code follows.

      D-Bus interface we are calling: We are interested in reading 'resultListWindow' 'v' variant, which returns a '(ddi)' struct (used for testing this bug).

      <method name="RequestResultList">
        <doc>
      	<line>RequestResultList = This method gets the poi result list (e.g. after a Search/Scroll call)</line>
        </doc>
        <arg name="poiSearchHandle" type="u" direction="in">
      	<doc>
      	  <line>poiSearchHandle = poi search unique handle</line>
      	</doc>
        </arg>
        <arg name="offset" type="q" direction="in">
      	<doc>
      	  <line>offset = starting offset of the newly requested list elements. If invalid (more that total list for instance) it starts from the begining.</line>
      	</doc>
        </arg>
        <arg name="maxWindowSize" type="q" direction="in">
      	<doc>
      	  <line>maxWindowSize = maximum number of elements that should be returned as result</line>
      	</doc>
        </arg>
        <arg name="attributes" type="as" direction="in">
      	<doc>
      	  <line>attributes = List of attributes name to retrieve. This is optional and the list could be empty.</line>
      	</doc>
        </arg>
        <arg name="statusValue" type="q" direction="out">
      	<doc>
      	  <line>statusValue = enum(INVALID,NOT_STARTED,SEARCHING,FINISHED, ... )</line>
      	</doc>
        </arg>
        <arg name="resultListSize" type="q" direction="out">
      	<doc>
      	  <line>resultListSize = Number of items of the results list</line>
      	</doc>
        </arg>
        <arg name="resultListWindow" type="v" direction="out">
      	<doc>
      	  <line>For testing purposes returns '(ddi)' in the variant.</line>
      	</doc>
        </arg>
        <error name="org.genivi.poiservice.poiSearch.Error.HandleNotAvailable">
      	<doc>
      	  <line>This error is generated if an application tries to use a poi search unique handle that is not available or not valid</line>
      	</doc>
        </error>
        <error name="org.genivi.poiservice.poiSearch.Error.InvalidPoiAttribute">
      	<doc>
      	  <line>This error is generated if an application tries to get one or more invalid poi attributes.</line>
      	</doc>
        </error>
      </method>
      

      Declaration of custom struct conforming to '(ddi)' signature:

      namespace poiservice
      {
        namespace poisearch
        {
          struct SLocation
          {
            double mLat;
            double mLon;
            qint32 mAlt;
      
            SLocation() : mLat(0.0), mLon(0.0), mAlt(0)
            {
            }
            bool operator==(const SLocation &other) const
            {
              return (mLat == other.mLat) && (mLon == other.mLon) && (mAlt == other.mAlt);
            }
          };
      
          QDBusArgument& operator<<(QDBusArgument& arg, const SLocation& location);
          const QDBusArgument& operator>>(const QDBusArgument& arg, SLocation& location);
        }
      }    // namespace poiservice::poisearch
      
      typedef QList<QString> TStringList;
      
      Q_DECLARE_METATYPE(poiservice::poisearch::SLocation)
      

      Marshall operator for custom struct:

      QDBusArgument& poiservice::poisearch::operator<<(QDBusArgument& arg, const SLocation& location)
      {
        arg.beginStructure();
        arg << location.mLat << location.mLon << location.mAlt;
        arg.endStructure(); 
        return arg; 
      }
      
      const QDBusArgument& poiservice::poisearch::operator>>(const QDBusArgument& arg, SLocation& location)
      {
        arg.beginStructure();
        arg >> location.mLat >> location.mLon >> location.mAlt;
        arg.endStructure();
        return arg; 
      }
      

      Registration of DBus metatypes:

      int metaTypeId = qDBusRegisterMetaType<SLocation>();
      

      Proxy generated by qdbusxml2cpp:

      inline QDBusPendingReply<ushort, ushort, QDBusVariant> RequestResultList(uint poiSearchHandle, ushort offset, ushort maxWindowSize, const QStringList &attributes)
      {
        QList<QVariant> argumentList;
        argumentList << QVariant::fromValue(poiSearchHandle) << QVariant::fromValue(offset) << QVariant::fromValue(maxWindowSize) << QVariant::fromValue(attributes);
        return asyncCallWithArgumentList(QLatin1String("RequestResultList"), argumentList);
      }
      

      Our wrapper code calling the proxy:

      void CPOIServicePOISearchWrapper::sltRequestResultList(quint32 poiSearchHandle, quint16 offset, quint16 maxWindowSize, TStringList attributes, quint16& outStatusValue, quint16& outResultListSize, QDBusVariant& outResultListWindow)
      {
        QDBusPendingReply<ushort,ushort,QDBusVariant> reply = mProxy->RequestResultList(poiSearchHandle, offset, maxWindowSize, attributes);
      
        reply.waitForFinished();
      
        if (reply.isValid())
        {
          outStatusValue = reply.argumentAt<0>();
          outResultListSize = reply.argumentAt<1>();
          outResultListWindow = reply.argumentAt<2>();
        }
        else
        {
          QString exceptionMessage = QString::number(reply.error().type()) + " - " + reply.error().name() + " - " + reply.error().message();
          throw std::runtime_error(exceptionMessage.toStdString());
        }
      }
      

      Our code calling the wrapper: I have added some comments explaining what is going wrong.

        quint16 outStatusValue;
        quint16 outResultSize;
        QDBusVariant outVariant;
        QList<QString> stringList;
        // example call, we are interested in 'outVariant'
        mGeniviPoiSearch->sltRequestResultList(1, 0, 1000, stringList, outStatusValue, outResultSize, outVariant);
      
        QVariant variant = outVariant.variant();
        qDebug() << "Variant type: " << variant.type();
        // output of the above line: Variant type: QVariant::QPaintBufferCacheEntry 
      
        int userType = variant.userType();
        qDebug() << "Variant usertype: " << userType;
        // output of the above line: Variant usertype:  1028 
      
        if (variant.canConvert<poiservice::poisearch::SLocation>())
        {
          qDebug() << "CAN convert to SLocation";
        }
        else
        {
          // this code is executed, conversion fails. 
          qDebug() << "Can NOT convert to SLocation";
        }
      
        // also, this results in 'empty' struct:
        poiservice::poisearch::SLocation location = variant.value<poiservice::poisearch::SLocation>();
      

      So it seems unmarshalling of complex types in DBus 'v' variants not working.
      The resulting value from variant.type() is QPaintBufferCacheEntry (see comments in last code block).

      Attachments

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          People

            thiago Thiago Macieira
            chrisco Chris Coppens
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews

                There are no open Gerrit changes